Quote:
Originally Posted by hack0r89
could you (if you have time) document what you found (functions, reversed code) and maybe how you got it?
because as mentioned i just got that strange CRC calculation
|
Sure, after my previous versions of this project were detected time after time, I decided I needed to understand the whole system if I wanted to get around it. So, I started looking for the answer to the first important question, how does the csro security get loaded into the process?
If you watched the last update, you'll notice the
rdmex files were updated as well as
data/ahclient.dat. After looking for new processes being started and tracing where the
cltax.cc file is used (inside the security code, which is after it is already loaded) the only thing left to look at was how
ahclient.dat was used.
Since the
ahclient.dat file is inside the PK2, that means they have to access it through the GFXFileManager DLL interface. I tried searching the client for referenced text strings for
ahclient, but none were found. So, I just set a breakpoint inside the PK2 lookup function. Just find a known pk2 file access, like
type.txt in the client and you can set a breakpoint inside the DLL to know the exact address.
From there, the breakpoint was triggered with a file name of
ahclient.dat. I back traced the call into the client logic that accessed the file. The file name is 'encrypted' so to speak and is unencrypted at runtime, which explains why no string references were found. Once the file was loaded, it is copied again to a new buffer while the old one was destroyed, so the next thing to do was trace the access to the contents.
I noticed it had some weird access logic to it. In doing so, I skipped over the logic that built this new logic (which is created, used, then destroyed), but I only focused on the AHClient buffer. The same logic that is used to unpack and rebuild the logic used for the AHClient buffer is also used in the client to unpack and rebuild the AHClient itself.
This function is what rebuilds the AHClient in the process:
Code:
00A43DE0 /$ 83EC 30 SUB ESP,30
00A43DE3 |. 55 PUSH EBP
00A43DE4 |. 8B6C24 38 MOV EBP,DWORD PTR SS:[ESP+38]
00A43DE8 |. 85ED TEST EBP,EBP
00A43DEA |. 56 PUSH ESI
00A43DEB |. C74424 10 000>MOV DWORD PTR SS:[ESP+10],0
00A43DF3 |. 75 0B JNZ SHORT [edx]sro.00A43E00
00A43DF5 |. 5E POP ESI
00A43DF6 |. B8 01000000 MOV EAX,1
00A43DFB |. 5D POP EBP
00A43DFC |. 83C4 30 ADD ESP,30
00A43DFF |. C3 RETN
00A43E00 |> 8B45 00 MOV EAX,DWORD PTR SS:[EBP]
00A43E03 |. 33D2 XOR EDX,EDX
00A43E05 |. B9 90780000 MOV ECX,7890
00A43E0A |. F7F1 DIV ECX
00A43E0C |. 81FA 56040000 CMP EDX,456
00A43E12 |. 74 0B JE SHORT [edx]sro.00A43E1F
00A43E14 |. 5E POP ESI
00A43E15 |. B8 02000000 MOV EAX,2
00A43E1A |. 5D POP EBP
00A43E1B |. 83C4 30 ADD ESP,30
00A43E1E |. C3 RETN
00A43E1F |> 0FB745 08 MOVZX EAX,WORD PTR SS:[EBP+8]
00A43E23 |. 66:3D 0100 CMP AX,1
00A43E27 |. 0F82 D3020000 JB [edx]sro.00A44100
00A43E2D |. 66:3D 0A00 CMP AX,0A
00A43E31 |. 0F87 C9020000 JA [edx]sro.00A44100
00A43E37 |. 817D 04 80841>CMP DWORD PTR SS:[EBP+4],1E8480
00A43E3E |. 76 0B JBE SHORT [edx]sro.00A43E4B
00A43E40 |. 5E POP ESI
00A43E41 |. B8 04000000 MOV EAX,4
00A43E46 |. 5D POP EBP
00A43E47 |. 83C4 30 ADD ESP,30
00A43E4A |. C3 RETN
00A43E4B |> 8B45 0E MOV EAX,DWORD PTR SS:[EBP+E]
00A43E4E |. 85C0 TEST EAX,EAX
00A43E50 |. 0F84 9F020000 JE [edx]sro.00A440F5
00A43E56 |. 3D FFFFFF8F CMP EAX,8FFFFFFF
00A43E5B |. 0F87 94020000 JA [edx]sro.00A440F5
00A43E61 |. 8B45 16 MOV EAX,DWORD PTR SS:[EBP+16]
00A43E64 |. 85C0 TEST EAX,EAX
00A43E66 |. 0F84 7E020000 JE [edx]sro.00A440EA
00A43E6C |. 3D FFFFFF8F CMP EAX,8FFFFFFF
00A43E71 |. 0F87 73020000 JA [edx]sro.00A440EA
00A43E77 |. 8B55 1A MOV EDX,DWORD PTR SS:[EBP+1A]
00A43E7A |. 8D4424 14 LEA EAX,DWORD PTR SS:[ESP+14]
00A43E7E |. 50 PUSH EAX ; /pSystemInfo
00A43E7F |. 8D74D5 1E LEA ESI,DWORD PTR SS:[EBP+EDX*8+1E] ; |
00A43E83 |. FF15 18E2C100 CALL NEAR DWORD PTR DS:[<&KERNEL32.GetSy>; \GetSystemInfo
00A43E89 |. 8B45 04 MOV EAX,DWORD PTR SS:[EBP+4]
00A43E8C |. 8B4C24 18 MOV ECX,DWORD PTR SS:[ESP+18]
00A43E90 |. 33D2 XOR EDX,EDX
00A43E92 |. F7F1 DIV ECX
00A43E94 |. 85D2 TEST EDX,EDX
00A43E96 |. 74 03 JE SHORT [edx]sro.00A43E9B
00A43E98 |. 83C0 01 ADD EAX,1
00A43E9B |> 0FAFC8 IMUL ECX,EAX
00A43E9E |. 6A 40 PUSH 40 ; /Protect = PAGE_EXECUTE_READWRITE
00A43EA0 |. 68 00100000 PUSH 1000 ; |AllocationType = MEM_COMMIT
00A43EA5 |. 51 PUSH ECX ; |Size
00A43EA6 |. 6A 00 PUSH 0 ; |Address = NULL
00A43EA8 |. FF15 88E2C100 CALL NEAR DWORD PTR DS:[<&KERNEL32.Virtu>; \VirtualAlloc
00A43EAE |. 85C0 TEST EAX,EAX
00A43EB0 |. 8B4C24 40 MOV ECX,DWORD PTR SS:[ESP+40]
00A43EB4 |. 8901 MOV DWORD PTR DS:[ECX],EAX
00A43EB6 |. 75 0B JNZ SHORT [edx]sro.00A43EC3
00A43EB8 |. 5E POP ESI
00A43EB9 |. B8 07000000 MOV EAX,7
00A43EBE |. 5D POP EBP
00A43EBF |. 83C4 30 ADD ESP,30
00A43EC2 |. C3 RETN
00A43EC3 |> 33C9 XOR ECX,ECX
00A43EC5 |. 394D 1A CMP DWORD PTR SS:[EBP+1A],ECX
00A43EC8 |. 53 PUSH EBX
00A43EC9 |. 57 PUSH EDI
00A43ECA |. 76 2C JBE SHORT [edx]sro.00A43EF8
00A43ECC |. 8B5424 4C MOV EDX,DWORD PTR SS:[ESP+4C]
00A43ED0 |. 33C0 XOR EAX,EAX
00A43ED2 |> 8B5C24 48 /MOV EBX,DWORD PTR SS:[ESP+48]
00A43ED6 |. 03C0 |ADD EAX,EAX
00A43ED8 |. 03C0 |ADD EAX,EAX
00A43EDA |. 03C0 |ADD EAX,EAX
00A43EDC |. 8B7C28 1E |MOV EDI,DWORD PTR DS:[EAX+EBP+1E]
00A43EE0 |. 893C10 |MOV DWORD PTR DS:[EAX+EDX],EDI
00A43EE3 |. 8B7C28 22 |MOV EDI,DWORD PTR DS:[EAX+EBP+22]
00A43EE7 |. 033B |ADD EDI,DWORD PTR DS:[EBX]
00A43EE9 |. 83C1 01 |ADD ECX,1
00A43EEC |. 897C10 04 |MOV DWORD PTR DS:[EAX+EDX+4],EDI
00A43EF0 |. 0FB7C1 |MOVZX EAX,CX
00A43EF3 |. 3B45 1A |CMP EAX,DWORD PTR SS:[EBP+1A]
00A43EF6 |.^ 72 DA \JB SHORT [edx]sro.00A43ED2
00A43EF8 |> 8B5424 48 MOV EDX,DWORD PTR SS:[ESP+48]
00A43EFC |. 8B3A MOV EDI,DWORD PTR DS:[EDX]
00A43EFE |. 8B45 16 MOV EAX,DWORD PTR SS:[EBP+16]
00A43F01 |. 33DB XOR EBX,EBX
00A43F03 |. 8947 16 MOV DWORD PTR DS:[EDI+16],EAX
00A43F06 |. 66:395D 08 CMP WORD PTR SS:[EBP+8],BX
00A43F0A |. 897C24 10 MOV DWORD PTR SS:[ESP+10],EDI
00A43F0E |. 76 28 JBE SHORT [edx]sro.00A43F38
00A43F10 |> 8B4C24 48 /MOV ECX,DWORD PTR SS:[ESP+48]
00A43F14 |. 8B01 |MOV EAX,DWORD PTR DS:[ECX]
00A43F16 |. 8B7E 08 |MOV EDI,DWORD PTR DS:[ESI+8]
00A43F19 |. 0306 |ADD EAX,DWORD PTR DS:[ESI]
00A43F1B |. 57 |PUSH EDI
00A43F1C |. 83C6 0C |ADD ESI,0C
00A43F1F |. 56 |PUSH ESI
00A43F20 |. 50 |PUSH EAX
00A43F21 |. E8 6ACEFCFF |CALL <[edx]sro.__memcopy>
00A43F26 |. 83C3 01 |ADD EBX,1
00A43F29 |. 83C4 0C |ADD ESP,0C
00A43F2C |. 03F7 |ADD ESI,EDI
00A43F2E |. 66:3B5D 08 |CMP BX,WORD PTR SS:[EBP+8]
00A43F32 |.^ 72 DC \JB SHORT [edx]sro.00A43F10
00A43F34 |. 8B7C24 10 MOV EDI,DWORD PTR SS:[ESP+10]
00A43F38 |> 8B5D 0E MOV EBX,DWORD PTR SS:[EBP+E]
00A43F3B |. 03DF ADD EBX,EDI
00A43F3D |. 895C24 14 MOV DWORD PTR SS:[ESP+14],EBX
00A43F41 |> 837B 04 00 /CMP DWORD PTR DS:[EBX+4],0
00A43F45 |. 75 0A |JNZ SHORT [edx]sro.00A43F51
00A43F47 |. 837B 0C 00 |CMP DWORD PTR DS:[EBX+C],0
00A43F4B |. 0F84 E3000000 |JE [edx]sro.00A44034
00A43F51 |> 8B73 0C |MOV ESI,DWORD PTR DS:[EBX+C]
00A43F54 |. 03F7 |ADD ESI,EDI
00A43F56 |. 56 |PUSH ESI
00A43F57 |. E8 94F6FFFF |CALL <[edx]sro._decrypt_string>
00A43F5C |. 83C4 04 |ADD ESP,4
00A43F5F |. 85C0 |TEST EAX,EAX
00A43F61 |. 0F87 4B010000 |JA [edx]sro.00A440B2
00A43F67 |. 56 |PUSH ESI ; /pModule
00A43F68 |. FF15 BCE1C100 |CALL NEAR DWORD PTR DS:[<&KERNEL32.GetM>; \GetModuleHandleA
00A43F6E |. 8BE8 |MOV EBP,EAX
00A43F70 |. 85ED |TEST EBP,EBP
00A43F72 |. 75 11 |JNZ SHORT [edx]sro.00A43F85
00A43F74 |. 56 |PUSH ESI ; /FileName
00A43F75 |. FF15 00E2C100 |CALL NEAR DWORD PTR DS:[<&KERNEL32.Load>; \LoadLibraryA
00A43F7B |. 8BE8 |MOV EBP,EAX
00A43F7D |. 85ED |TEST EBP,EBP
00A43F7F |. 0F84 37010000 |JE [edx]sro.00A440BC
00A43F85 |> 8BC6 |MOV EAX,ESI
00A43F87 |. 8D50 01 |LEA EDX,DWORD PTR DS:[EAX+1]
00A43F8A |. 8D9B 00000000 |LEA EBX,DWORD PTR DS:[EBX]
00A43F90 |> 8A08 |/MOV CL,BYTE PTR DS:[EAX]
00A43F92 |. 83C0 01 ||ADD EAX,1
00A43F95 |. 84C9 ||TEST CL,CL
00A43F97 |.^ 75 F7 |\JNZ SHORT [edx]sro.00A43F90
00A43F99 |. 2BC2 |SUB EAX,EDX
00A43F9B |. 50 |PUSH EAX ; /n
00A43F9C |. 6A 00 |PUSH 0 ; |c = 00
00A43F9E |. 56 |PUSH ESI ; |s
00A43F9F |. E8 DC95FCFF |CALL <[edx]sro._memset> ; \_memset
00A43FA4 |. 8B7C24 1C |MOV EDI,DWORD PTR SS:[ESP+1C]
00A43FA8 |. 8B1B |MOV EBX,DWORD PTR DS:[EBX]
00A43FAA |. 8B5424 20 |MOV EDX,DWORD PTR SS:[ESP+20]
00A43FAE |. 8B72 10 |MOV ESI,DWORD PTR DS:[EDX+10]
00A43FB1 |. 8B043B |MOV EAX,DWORD PTR DS:[EBX+EDI]
00A43FB4 |. 03DF |ADD EBX,EDI
00A43FB6 |. 83C4 0C |ADD ESP,0C
00A43FB9 |. 03F7 |ADD ESI,EDI
00A43FBB |. 85C0 |TEST EAX,EAX
00A43FBD |. 74 5F |JE SHORT [edx]sro.00A4401E
00A43FBF |> 79 11 |/JNS SHORT [edx]sro.00A43FD2
00A43FC1 |. 25 FFFF0000 ||AND EAX,0FFFF
00A43FC6 |. 50 ||PUSH EAX ; /ProcNameOrOrdinal
00A43FC7 |. 55 ||PUSH EBP ; |hModule
00A43FC8 |. FF15 B8E1C100 ||CALL NEAR DWORD PTR DS:[<&KERNEL32.Get>; \GetProcAddress
00A43FCE |. 8906 ||MOV DWORD PTR DS:[ESI],EAX
00A43FD0 |. EB 3F ||JMP SHORT [edx]sro.00A44011
00A43FD2 |> 8D7C38 02 ||LEA EDI,DWORD PTR DS:[EAX+EDI+2]
00A43FD6 |. 57 ||PUSH EDI
00A43FD7 |. E8 14F6FFFF ||CALL <[edx]sro._decrypt_string>
00A43FDC |. 83C4 04 ||ADD ESP,4
00A43FDF |. 85C0 ||TEST EAX,EAX
00A43FE1 |. 0F87 DD000000 ||JA [edx]sro.00A440C4
00A43FE7 |. 57 ||PUSH EDI ; /ProcNameOrOrdinal
00A43FE8 |. 55 ||PUSH EBP ; |hModule
00A43FE9 |. FF15 B8E1C100 ||CALL NEAR DWORD PTR DS:[<&KERNEL32.Get>; \GetProcAddress
00A43FEF |. 8906 ||MOV DWORD PTR DS:[ESI],EAX
00A43FF1 |. 8BC7 ||MOV EAX,EDI
00A43FF3 |. 8D50 01 ||LEA EDX,DWORD PTR DS:[EAX+1]
00A43FF6 |> 8A08 ||/MOV CL,BYTE PTR DS:[EAX]
00A43FF8 |. 83C0 01 |||ADD EAX,1
00A43FFB |. 84C9 |||TEST CL,CL
00A43FFD |.^ 75 F7 ||\JNZ SHORT [edx]sro.00A43FF6
00A43FFF |. 2BC2 ||SUB EAX,EDX
00A44001 |. 50 ||PUSH EAX ; /n
00A44002 |. 6A 00 ||PUSH 0 ; |c = 00
00A44004 |. 57 ||PUSH EDI ; |s
00A44005 |. E8 7695FCFF ||CALL <[edx]sro._memset> ; \_memset
00A4400A |. 8B7C24 1C ||MOV EDI,DWORD PTR SS:[ESP+1C]
00A4400E |. 83C4 0C ||ADD ESP,0C
00A44011 |> 8B43 04 ||MOV EAX,DWORD PTR DS:[EBX+4]
00A44014 |. 83C3 04 ||ADD EBX,4
00A44017 |. 83C6 04 ||ADD ESI,4
00A4401A |. 85C0 ||TEST EAX,EAX
00A4401C |.^ 75 A1 |\JNZ SHORT [edx]sro.00A43FBF
00A4401E |> 834424 14 14 |ADD DWORD PTR SS:[ESP+14],14
00A44023 |. 8B6C24 44 |MOV EBP,DWORD PTR SS:[ESP+44]
00A44027 |. 8B7C24 10 |MOV EDI,DWORD PTR SS:[ESP+10]
00A4402B |. 8B5C24 14 |MOV EBX,DWORD PTR SS:[ESP+14]
00A4402F |.^ E9 0DFFFFFF \JMP [edx]sro.00A43F41
00A44034 |> 8B55 12 MOV EDX,DWORD PTR SS:[EBP+12]
00A44037 |. 85D2 TEST EDX,EDX
00A44039 |. 74 57 JE SHORT [edx]sro.00A44092
00A4403B |. 03D7 ADD EDX,EDI
00A4403D |. 833A 00 CMP DWORD PTR DS:[EDX],0
00A44040 |. 74 50 JE SHORT [edx]sro.00A44092
00A44042 |> 8B42 04 /MOV EAX,DWORD PTR DS:[EDX+4]
00A44045 |. 8D72 08 |LEA ESI,DWORD PTR DS:[EDX+8]
00A44048 |. 03C2 |ADD EAX,EDX
00A4404A |. 3BF0 |CMP ESI,EAX
00A4404C |. 73 3C |JNB SHORT [edx]sro.00A4408A
00A4404E |. 8BFF |MOV EDI,EDI
00A44050 |> 0FB706 |/MOVZX EAX,WORD PTR DS:[ESI]
00A44053 |. 8BC8 ||MOV ECX,EAX
00A44055 |. 81E1 00F00000 ||AND ECX,0F000
00A4405B |. 81F9 00300000 ||CMP ECX,3000
00A44061 |. 75 12 ||JNZ SHORT [edx]sro.00A44075
00A44063 |. 25 FF0F0000 ||AND EAX,0FFF
00A44068 |. 0302 ||ADD EAX,DWORD PTR DS:[EDX]
00A4406A |. 8BCF ||MOV ECX,EDI
00A4406C |. 2B4D 0A ||SUB ECX,DWORD PTR SS:[EBP+A]
00A4406F |. 03C7 ||ADD EAX,EDI
00A44071 |. 0108 ||ADD DWORD PTR DS:[EAX],ECX
00A44073 |. EB 04 ||JMP SHORT [edx]sro.00A44079
00A44075 |> 85C9 ||TEST ECX,ECX
00A44077 |. 75 2F ||JNZ SHORT [edx]sro.00A440A8
00A44079 |> 66:C706 0000 ||MOV WORD PTR DS:[ESI],0
00A4407E |. 8B42 04 ||MOV EAX,DWORD PTR DS:[EDX+4]
00A44081 |. 83C6 02 ||ADD ESI,2
00A44084 |. 03C2 ||ADD EAX,EDX
00A44086 |. 3BF0 ||CMP ESI,EAX
00A44088 |.^ 72 C6 |\JB SHORT [edx]sro.00A44050
00A4408A |> 0352 04 |ADD EDX,DWORD PTR DS:[EDX+4]
00A4408D |. 833A 00 |CMP DWORD PTR DS:[EDX],0
00A44090 |.^ 75 B0 \JNZ SHORT [edx]sro.00A44042
00A44092 |> 8B4D 16 MOV ECX,DWORD PTR SS:[EBP+16]
00A44095 |. 6A 00 PUSH 0
00A44097 |. 6A 01 PUSH 1
00A44099 |. 57 PUSH EDI
00A4409A |. 03CF ADD ECX,EDI
00A4409C |. FFD1 CALL NEAR ECX
00A4409E |. 5F POP EDI
00A4409F |. 5B POP EBX
00A440A0 |. 5E POP ESI
00A440A1 |. 33C0 XOR EAX,EAX
00A440A3 |. 5D POP EBP
00A440A4 |. 83C4 30 ADD ESP,30
00A440A7 |. C3 RETN
Basically what it does is update the runetime IAT with the values of the current process and loads the image into memory, like the Windows loader would. At this stage, the AHClient buffer has already been uncompressed in memory from the previous logic (so it's uncompressed, then loaded into memory). In addition, a few other addresses are updated as needed for proper execution.
Once that function completes, the AHClient is loaded into memory and is ready to be used by the client. There is a set of logic that is returned to from that function that makes calls into the AHClient. That code looks like this:
Code:
00A42C3F . C645 FC 04 MOV BYTE PTR SS:[EBP-4],4
00A42C43 . 833D 7025F800>CMP DWORD PTR DS:[F82570],0
00A42C4A . 74 10 JE SHORT [edx]sro.00A42C5C
00A42C4C . 68 EA030000 PUSH 3EA
00A42C51 . 68 D8CBD300 PUSH [edx]sro.00D3CBD8
00A42C56 . FF15 7025F800 CALL NEAR DWORD PTR DS:[F82570] ; <-
00A42C5C > 833D 6C25F800>CMP DWORD PTR DS:[F8256C],0
00A42C63 . 74 11 JE SHORT [edx]sro.00A42C76
00A42C65 . B9 7825F800 MOV ECX,[edx]sro.00F82578
00A42C6A . E8 01170000 CALL [edx]sro.00A44370
00A42C6F . 50 PUSH EAX
00A42C70 . FF15 6C25F800 CALL NEAR DWORD PTR DS:[F8256C] ; <-
00A42C76 > EB 4F JMP SHORT [edx]sro.00A42CC7
00A42C78 . B9 9C25F800 MOV ECX,[edx]sro.00F8259C
00A42C7D . E8 EE160000 CALL [edx]sro.00A44370
00A42C82 . 85C0 TEST EAX,EAX
00A42C84 . 74 11 JE SHORT [edx]sro.00A42C97
00A42C86 . B9 9C25F800 MOV ECX,[edx]sro.00F8259C
00A42C8B . E8 E0160000 CALL [edx]sro.00A44370
00A42C90 . 50 PUSH EAX
00A42C91 . FF15 6425F800 CALL NEAR DWORD PTR DS:[F82564] ; <-
00A42C97 > E8 54FAFFFF CALL [edx]sro.00A426F0
00A42C9C . 6A 00 PUSH 0
00A42C9E . B9 9C25F800 MOV ECX,[edx]sro.00F8259C
00A42CA3 . E8 E8150000 CALL [edx]sro.00A44290
00A42CA8 . 6A 00 PUSH 0
00A42CAA . B9 7825F800 MOV ECX,[edx]sro.00F82578
00A42CAF . E8 DC150000 CALL [edx]sro.00A44290
00A42CB4 . C745 C0 ECFFF>MOV DWORD PTR SS:[EBP-40],-14
00A42CBB . B8 D02CA400 MOV EAX,[edx]sro.00A42CD0
00A42CC0 . C3 RETN
00A42CC1 . B8 C72CA400 MOV EAX,[edx]sro.00A42CC7
00A42CC6 . C3 RETN
00A42CC7 > C745 FC 03000>MOV DWORD PTR SS:[EBP-4],3
00A42CCE . EB 17 JMP SHORT [edx]sro.00A42CE7
00A42CD0 . C745 FC FFFFF>MOV DWORD PTR SS:[EBP-4],-1
00A42CD7 . 8D4D EC LEA ECX,DWORD PTR SS:[EBP-14]
00A42CDA . E8 A1150000 CALL [edx]sro.00A44280
00A42CDF . 8B45 C0 MOV EAX,DWORD PTR SS:[EBP-40]
00A42CE2 . E9 64020000 JMP [edx]sro.00A42F4B
00A42CE7 > C645 FC 06 MOV BYTE PTR SS:[EBP-4],6
00A42CEB . C745 D8 00000>MOV DWORD PTR SS:[EBP-28],0
00A42CF2 . 8D55 D8 LEA EDX,DWORD PTR SS:[EBP-28]
00A42CF5 . 52 PUSH EDX
00A42CF6 . FF15 5C25F800 CALL NEAR DWORD PTR DS:[F8255C] ; <-
00A42CFC . 85C0 TEST EAX,EAX
00A42CFE . 7D 34 JGE SHORT [edx]sro.00A42D34
00A42D00 . 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-28]
00A42D03 . 50 PUSH EAX
00A42D04 . FF15 6425F800 CALL NEAR DWORD PTR DS:[F82564] ; <-
00A42D0A . E8 E1F9FFFF CALL [edx]sro.00A426F0
The lines with arrows show the function calls into the memory. Since the address changes, global variables are used to store the addresses of the client functions. The logic for storing the function pointers can be found earlier and looks like this:
Code:
00A429AE 8B4424 3C MOV EAX,DWORD PTR SS:[ESP+3C]
00A429B2 3BC3 CMP EAX,EBX
00A429B4 8B5424 34 MOV EDX,DWORD PTR SS:[ESP+34]
00A429B8 8B7C24 44 MOV EDI,DWORD PTR SS:[ESP+44]
00A429BC 8B7424 4C MOV ESI,DWORD PTR SS:[ESP+4C]
00A429C0 8B6C24 54 MOV EBP,DWORD PTR SS:[ESP+54]
00A429C4 8B4C24 5C MOV ECX,DWORD PTR SS:[ESP+5C]
00A429C8 8915 6425F800 MOV DWORD PTR DS:[F82564],EDX
00A429CE A3 5C25F800 MOV DWORD PTR DS:[F8255C],EAX
00A429D3 893D 6C25F800 MOV DWORD PTR DS:[F8256C],EDI
00A429D9 8935 6825F800 MOV DWORD PTR DS:[F82568],ESI
00A429DF 892D 7025F800 MOV DWORD PTR DS:[F82570],EBP
00A429E5 890D 6025F800 MOV DWORD PTR DS:[F82560],ECX
Those function addresses are actually calculated and stored into an array in the AHClient rebuilding function previously pasted. Once all that is setup, then the client continues to work normally as needed. At this stage, you'd just have to trace all of the calls into and out of the module to work on how to emulate it and figure out what triggers the memory scans and the other functionality. That's the point I'm at right now.
So just to wrap up: sro_client loads ahclient.dat from data.pk2. sro_client unpacks an embedded executable into memory and passes the compressed ahclient.dat buffer to it. The new executable in memory uncompresses it and then is unloaded from memory. sro_client loads the uncompressed AHClient into memory for execution. Finally, sro_client interacts with AHClient through a series of function calls. Likewise, AHClient interacts with sro_client through registered function calls.
It's a lot of tracing and going through the logic over and over until it all comes together. I actually skipped the first process sro_client loads into memory,so I'll go back to that later. It was fairly obvious which compression method was used because it was so common I'd seen it dozens of time, so I didn't really get into the specifics of what the first process does, besides the obvious uncompress data.
As for the client calling the AHClient functions and the AHClient calling the sro_client functions, I'm still working on tracing those and looking at what the individual calls do mentioned above. There's still a lot of code to go through and logic to be worked out since the AHClient runs its own threads and will send packets through sro_client to the server. On the bright side, that makes a clientless more easy since the security uses a user callback function to send data.
That's about what I have for now. I'll be looking at how the first packet is generated as well as some more details of the AHClient functions called tomorrow. It is very draining work, but it's a nice, fun challenge!