Quote:
Originally Posted by pachela
Hey guys. How to find this?
#define ATA_LUA_GETTOP
I finding getTopValue only. Or it's same?
|
LUA_GETTOP was a lil tricky, so I'll explain it a bit.
First, let's look at the Lua source code and let's find out which version of Lua Black Desert is using. After unpacking the BlackDesert64.exe, rebuilding any PE headers, and opening it up in IDA, do a search for "lua" and find a line similar to this:
Quote:
___:000000014294ADE0 0000008D C $Lua: Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio $\n$Authors: R. Ierusalimschy, L. H. de Figueiredo & W. Celes $\n$URL: $\n
|
We now know that BDO uses Lua 5.1.5.
So, if we go to the original source for 5.1.5, we find this page:
The file we're looking for is lbaselib.c (

).
Code:
/*
** If your system does not support `stdout', you can just remove this function.
** If you need, you can define your own `print' function, following this
** model but changing `fputs' to put the strings at a proper place
** (a console window or a log file, for instance).
*/
static int luaB_print (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int i;
lua_getglobal(L, "tostring");
for (i=1; i<=n; i++) {
const char *s;
lua_pushvalue(L, -1); /* function to be called */
lua_pushvalue(L, i); /* value to print */
lua_call(L, 1, 1);
s = lua_tostring(L, -1); /* get result */
if (s == NULL)
return luaL_error(L, LUA_QL("tostring") " must return a string to "
LUA_QL("print"));
if (i>1) fputs("\t", stdout);
fputs(s, stdout);
lua_pop(L, 1); /* pop result */
}
fputs("\n", stdout);
return 0;
This is near the top of the file, the line we're interested in is line 32, " int n = lua_gettop(L); /* number of arguments */"
However, as you've already noticed, there is no "gettop" string relating to Lua, just a random gettopvalue which is not what we're looking for. So what do we do? Well, right below that is a lua_getglobal function calling for
tostring, so let's look and see if IDA has that.
Quote:
|
___:000000014294BB68 00000009 C tostring
|
Success, let's follow up on this lead. Double click the string and xref aToString.
Code:
___:0000000141667640
___:0000000141667640 ; =============== S U B R O U T I N E =======================================
___:0000000141667640
___:0000000141667640
___:0000000141667640 sub_141667640 proc near
___:0000000141667640
___:0000000141667640 arg_0 = qword ptr 8
___:0000000141667640 arg_8 = qword ptr 10h
___:0000000141667640 arg_10 = qword ptr 18h
___:0000000141667640
___:0000000141667640 mov [rsp+arg_0], rbx
___:0000000141667645 mov [rsp+arg_8], rbp
___:000000014166764A mov [rsp+arg_10], rsi
___:000000014166764F push rdi
___:0000000141667650 sub rsp, 20h
___:0000000141667654 mov rdi, rcx
___:0000000141667657 call sub_14165A110
___:000000014166765C lea r8, aTostring ; "tostring"
___:0000000141667663 mov edx, 0FFFFD8EEh
___:0000000141667668 mov rcx, rdi
___:000000014166766B mov ebp, eax
___:000000014166766D call sub_14165A010
___:0000000141667672 mov ebx, 1
___:0000000141667677 cmp ebp, ebx
___:0000000141667679 jl loc_141667705
___:000000014166767F nop
If you use IDA Pro, you can then progress further examining the Psuedocode:
Code:
__int64 __fastcall sub_141667640(__int64 a1)
{
__int64 v1; // rdi@1
int v2; // ebp@1
signed int i; // ebx@1
const char *v4; // rax@2
const char *v5; // rsi@2
FILE *v6; // rax@4
FILE *v7; // rax@5
FILE *v8; // rax@6
v1 = a1;
v2 = sub_14165A110();
sub_14165A010(v1, 4294957294i64, "tostring");
for ( i = 1; i <= v2; ++i )
{
sub_14165A810(v1, 0xFFFFFFFFi64);
sub_14165A810(v1, (unsigned int)i);
sub_141659BA0(v1, 1i64, 1i64);
LODWORD(v4) = sub_14165AF70(v1, 0xFFFFFFFFi64, 0i64);
v5 = v4;
if ( !v4 )
sub_14165BA20(v1, "'tostring' must return a string to 'print'");
if ( i > 1 )
{
LODWORD(v6) = j___acrt_iob_func(1i64);
j_fputs("\t", v6);
}
LODWORD(v7) = j___acrt_iob_func(1i64);
j_fputs(v5, v7);
sub_14165AD90(v1, 4294967294i64);
}
LODWORD(v8) = j___acrt_iob_func(1i64);
j_fputs("\n", v8);
return 0i64;
}
We have two very similar lines here.
Lua Source:
Quote:
return luaL_error(L, LUA_QL("tostring") " must return a string to "
LUA_QL("print"));
|
IDA Psuedocode:
Quote:
|
sub_14165BA20(v1, "'tostring' must return a string to 'print'");
|
So we now have confirmed that this is the exact spot of the source clip above. Looking back at the Lua Source:
Code:
static int luaB_print (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int i;
lua_getglobal(L, "tostring");
We can see that
lua_gettop is called
2 lines above "tostring". Let's look at the Psuedocode again:
Code:
v1 = a1;
v2 = sub_14165A110();
sub_14165A010(v1, 4294957294i64, "tostring");
There isn't a function called two lines above, however there is one called one line above. Let's investigate further:
Code:
__int64 __fastcall sub_14165A110(__int64 a1)
{
return (*(_QWORD *)(a1 + 16) - *(_QWORD *)(a1 + 24)) >> 4;
}
In IDA, this is the Psuedocode used to represent LUA_GETTOP. So your address would be:
0x000000014165A110. I'd like to remind anyone reading this in the future that this address is only valid for build 290475 (NA).