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

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


2.由此判断加密用lua相关. hook lua5.luaL_loadbuffer,将所有的lua文件dump下来.
查看,发现 
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.再回头分析[1]处的 取用户名密码,得知,
00410D7D   > \6A 00         push    0
00410D7F   .  6A 01         push    1                                                   ;  第一个参数 Login.m_szAccount
00410D81   .  56            push    esi                                                 ;  参数: db [[esi+C]]+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 [[esi+C]+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 [EAX] == "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 [esi+14]
0016AA2B    8B42 04         mov     eax, dword ptr [edx+4]
0016AA2E    8B08            mov     ecx, dword ptr [eax]
0016AA30    8B51 10         mov     edx, dword ptr [ecx+10]
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.经过[6]的操作,进入GetPassword().
0CF5C200   .  83EC 44       sub     esp, 44                                             ;  frame:Lookup("Edit_Password"):GetPassword()
0CF5C203   .  A1 2C40FC0C   mov     eax, dword ptr [CFC402C]
0CF5C208   .  33C4          xor     eax, esp
0CF5C20A   .  894424 40     mov     dword ptr [esp+40], eax
0CF5C20E   .  56            push    esi
0CF5C20F   .  8B7424 4C     mov     esi, dword ptr [esp+4C]
0CF5C213   .  6A 3F         push    3F                                                  ; /n = 3F (63.)
0CF5C215   .  8D4424 09     lea     eax, dword ptr [esp+9]                              ; |
0CF5C219   .  6A 00         push    0                                                   ; |c = 00
0CF5C21B   .  50            push    eax                                                 ; |s
0CF5C21C   .  C64424 10 00  mov     byte ptr [esp+10], 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 [esp+4]
0CF5C282   .  51            push    ecx
0CF5C283   .  8BC8          mov     ecx, eax
0CF5C285   .  E8 86A80300   call    0CF96B10                                            ;  ***********************encrypt password********************
0CF5C28A   >  8D5424 04     lea     edx, dword ptr [esp+4]
0CF5C28E   .  52            push    edx
0CF5C28F   .  56            push    esi
0CF5C290   .  E8 BFDE0400   call    <jmp.&Lua5.lua_pushstring>
0CF5C295   .  8B4C24 4C     mov     ecx, dword ptr [esp+4C]
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 [esp+24], eax
0CF96C3B   .  51            push    ecx                                                 ;  
0CF96C3C   .  8D4424 28     lea     eax, dword ptr [esp+28]
0CF96C40   .  66:895C24 1A  mov     word ptr [esp+1A], bx
0CF96C45   .  E8 76AEFBFF   call    0CF51AC0                                            ;  取单个字符"78787878"
0CF96C4A   .  C68424 D00000>mov     byte ptr [esp+D0], 1
0CF96C52   .  8B5424 24     mov     edx, dword ptr [esp+24]
0CF96C56   .  52            push    edx                                                 ;  组成字符
0CF96C57   .  8D8C24 AC0000>lea     ecx, dword ptr [esp+AC]
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测试游戏加密后的密码,正确。可逆。

11.