zbj801 发表于 2013-8-3 15:06:55

逆个 用了lua的程序

// ************** 跟踪xx游戏加密用户名密码过程 ****************************//
1.在发包处向上跟,得到发包加密处.再向上跟踪,得到
00410DB5 > \55 push ebp
00410DB6 . 6A 00 push 0
00410DB8 . 6A 02 push 2 ; 第一个参数 Login.m_szPassword
00410DBA . 56 push esi ; 参数: db [+10]+10
00410DBB . E8 8CE50A00 call <jmp.&Lua5.lua_tolstring> ; get_password

取加密后的密码.再向上跟,测晕死在lua5.dll中.在此函数开始处下断,用WinHex查看内存,发现加密后的密码已经出现.


2.由此判断加密用lua相关. hook lua5.luaL_loadbuffer,将所有的lua文件dump下来.
//dump lua,看luaL_loadbuffer 的原形,hook luaL_loadbuffer,把传进来的buffer写成文件就可以了
查看,发现
ui\config\loginpassword.lua
ui\login.lua
等可疑文件,分析,得到结果,
// --------------------------------------
SaveAccountAndPassword=function()
local frame = Station.Lookup("Normal/LoginPassword/WndPassword")
Login.m_szAccount = frame:Lookup("Edit_Account"):GetText()
Login.m_szPassword = frame:Lookup("Edit_Password"):GetPassword()
.........
// --------------------------------------
StepNext=function()
.........
elseif Login.m_StateLeaveFunction == Login.LeavePassword then
LoginPassword.SaveAccountAndPassword()
if Login.m_bRememberAccount and IsUserDataExist() or Login.m_bSelectServer then
Login.RequestLogin(g_tGlue.tLoginString["CONNECTING"], true)
.........

// --------------------------------------
RequestLogin=function(szMsg, bShowError)
.........
if Login.m_szAccount and Login.m_szPassword then
if not Login.m_szServerIP or not Login.m_nServerPort then
LoadUserData(Login.m_szAccount)
end

local szRegionName, szServerName = LoginServerList.GetSelectedServer()
Login.SelectServer(szRegionName, szServerName)

Login.BeginWait(szMsg)

Login_CancelLogin()
Login_SetGatewayAddress(Login.m_szServerIP, Login.m_nServerPort)
Login_BeginLogin(Login.m_szAccount, Login.m_szPassword)
elseif bShowError then
.........
// --------------------------------------

3.再回头分析处的 取用户名密码,得知,
00410D7D > \6A 00 push 0
00410D7F . 6A 01 push 1 ; 第一个参数 Login.m_szAccount
00410D81 . 56 push esi ; 参数: db []+10
00410D82 . E8 C5E50A00 call <jmp.&Lua5.lua_tolstring> ; getu_user_name
00410D87 . 83C4 0C add esp, 0C

00410DB5 > \55 push ebp
00410DB6 . 6A 00 push 0
00410DB8 . 6A 02 push 2 ; 第二个参数 Login.m_szPassword
00410DBA . 56 push esi ; 参数: db [+10]+10
00410DBB . E8 8CE50A00 call <jmp.&Lua5.lua_tolstring> ; get_password
00410DC0 . 8BE8 mov ebp, eax

,,判断此处便是lua脚本中的RequestLogin函数中的Login_BeginLogin(Login.m_szAccount, Login.m_szPassword).
猜想
lua脚本中的
Login_CancelLogin()
Login_SetGatewayAddress()
Login_BeginLogin()
都是主程序中的函数.

4.对lua乱跟一通后得知,在Lua脚本中出现的常量这符串都会使用Lua5::lua_tolstring函数获取.

5对Lua5::lua_tolstring结尾处下条件断 STRING == "Normal"
得到"Normal/LoginPassword/WndPassword"
与lua脚本中的
local frame = Station.Lookup("Normal/LoginPassword/WndPassword")
对应


5.再断Lua5::lua_tolstring入口,得到"Edit_Account" 和 "Edit_Password"
再到lua_tolstring的返回处,跟回上一层,得到一处call reg,是lua的总调用,
0016AA28 8B56 14 mov edx, dword ptr
0016AA2B 8B42 04 mov eax, dword ptr
0016AA2E 8B08 mov ecx, dword ptr
0016AA30 8B51 10 mov edx, dword ptr
0016AA33 56 push esi
0016AA34 FFD2 call edx ; *****

即:Login.m_szAccount = frame:Lookup("Edit_Account"):GetText()
Lua对这行脚本会分为多个步骤执行。
a,取 "Edit_Account"
b, 调用 GetText()
c, 对Login.m_szAccount赋值


6.综合上面的分析,在断到local frame = Station.Lookup("Normal/LoginPassword/WndPassword") 之后,
再断Lua5::lua_tolstring入口,在得到"Edit_Password"之后,断
0016AA34 FFD2 call edx
即是Login.m_szPassword = frame:Lookup("Edit_Password"):GetPassword()中的GetPassword().

7.经过的操作,进入GetPassword().
0CF5C200 . 83EC 44 sub esp, 44 ; frame:Lookup("Edit_Password"):GetPassword()
0CF5C203 . A1 2C40FC0C mov eax, dword ptr
0CF5C208 . 33C4 xor eax, esp
0CF5C20A . 894424 40 mov dword ptr , eax
0CF5C20E . 56 push esi
0CF5C20F . 8B7424 4C mov esi, dword ptr
0CF5C213 . 6A 3F push 3F ; /n = 3F (63.)
0CF5C215 . 8D4424 09 lea eax, dword ptr ; |
0CF5C219 . 6A 00 push 0 ; |c = 00
0CF5C21B . 50 push eax ; |s
0CF5C21C . C64424 10 00 mov byte ptr , 0 ; |
0CF5C221 . E8 56EB0400 call <jmp.&MSVCR80.memset> ; \memset
0CF5C226 . 56 push esi
0CF5C227 . E8 70DF0400 call <jmp.&Lua5.lua_gettop>
0CF5C22C . 83C4 10 add esp, 10
0CF5C22F . 83F8 01 cmp eax, 1
0CF5C232 . 74 11 je short 0CF5C245
0CF5C234 . 68 1086FB0C push 0CFB8610 ; ASCII "UI::KWndClassScriptTable::LuaEdit_GetPassword"
0CF5C239 . 68 B20B0000 push 0BB2
0CF5C23E . 68 A0F2FA0C push 0CFAF2A0 ; ASCII "Lua_GetTopIndex(L) == 1"
0CF5C243 . EB 27 jmp short 0CF5C26C
0CF5C245 > 53 push ebx
0CF5C246 . 68 1076FB0C push 0CFB7610 ; ASCII "WndEdit"
0CF5C24B . BB 01000000 mov ebx, 1
0CF5C250 . E8 EBBDFFFF call 0CF58040
0CF5C255 . 83C4 04 add esp, 4
0CF5C258 . 85C0 test eax, eax
0CF5C25A . 5B pop ebx
0CF5C25B . 75 21 jnz short 0CF5C27E
0CF5C25D . 68 1086FB0C push 0CFB8610 ; ASCII "UI::KWndClassScriptTable::LuaEdit_GetPassword"
0CF5C262 . 68 B50B0000 push 0BB5
0CF5C267 . 68 7878FB0C push 0CFB7878 ; ASCII "pWnd"
0CF5C26C > 68 B0E6FA0C push 0CFAE6B0 ; ASCII "KGLOG_PROCESS_ERROR(%s) at line %d in %s",LF
0CF5C271 . 6A 07 push 7
0CF5C273 . FF15 2CE0FA0C call dword ptr [<&Engine_Lua5.KGLogPrintf>] ; Engine_L.KGLogPrintf
0CF5C279 . 83C4 14 add esp, 14
0CF5C27C . EB 0C jmp short 0CF5C28A
0CF5C27E > 8D4C24 04 lea ecx, dword ptr
0CF5C282 . 51 push ecx
0CF5C283 . 8BC8 mov ecx, eax
0CF5C285 . E8 86A80300 call 0CF96B10 ; ***********************encrypt password********************
0CF5C28A > 8D5424 04 lea edx, dword ptr
0CF5C28E . 52 push edx
0CF5C28F . 56 push esi
0CF5C290 . E8 BFDE0400 call <jmp.&Lua5.lua_pushstring>
0CF5C295 . 8B4C24 4C mov ecx, dword ptr
0CF5C299 . 83C4 08 add esp, 8
0CF5C29C . 5E pop esi
0CF5C29D . 33CC xor ecx, esp
0CF5C29F . B8 01000000 mov eax, 1
0CF5C2A4 . E8 FDDF0400 call 0CFAA2A6
0CF5C2A9 . 83C4 44 add esp, 44
0CF5C2AC . C3 retn

8.分析GetPassword(),得知
0CF5C285 . E8 86A80300 call 0CF96B10
这个call返回了加密后的密码.


9.再对 call 0CF96B10分析,得知
0CF96C37 . 894424 24 mov dword ptr , eax
0CF96C3B . 51 push ecx ;
0CF96C3C . 8D4424 28 lea eax, dword ptr
0CF96C40 . 66:895C24 1A mov word ptr , bx
0CF96C45 . E8 76AEFBFF call 0CF51AC0 ; 取单个字符"78787878"
0CF96C4A . C68424 D00000>mov byte ptr , 1
0CF96C52 . 8B5424 24 mov edx, dword ptr
0CF96C56 . 52 push edx ; 组成字符
0CF96C57 . 8D8C24 AC0000>lea ecx, dword ptr
0CF96C5E . FF15 FCE1FA0C call dword ptr [<&MSVCP80.std::basic_string<char,std::ch>; msvcp80.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator+=
......
......
0CF96CF5 . 50 push eax
0CF96CF6 . 52 push edx
0CF96CF7 . FF15 3CE0FA0C call dword ptr [<&Engine_Lua5.KG_EDStringToMD5String>] ; Engine_L.KG_EDStringToMD5String

密码是由Engine_L.KG_EDStringToMD5String进行加密,很可能是MD5.
跟进Engine_L.KG_EDStringToMD5String,发现
1000128A |. E8 11080000 call md5_init
10001296 |. E8 35080000 call md5_append
100012A5 |. E8 F6080000 call md5_finish

10.用MD5测试游戏加密后的密码,正确。可逆。
页: [1]
查看完整版本: 逆个 用了lua的程序