棋牌後臺程序


棋牌後臺程序


棋牌後臺程序

首先借助一些工具得到kernel32的ImageBase為起始解析PE,得到導出表.2.然後取出GetProcAddress函數地址,獲取指定的API3.Api hook破解該軟件分析代碼:

00400380 60 pushad ;

保存寄存器環境00400381 8B4424 44 mov eax, dword ptr [esp+0x44]00400385 25 0000FFFF and eax, 0xFFFF0000 ;

不為序號導出0040038A 66:8138 4D5A cmp word ptr [eax], 0x5A4D ; 判斷MZ0040038F 74 07 je short 00400398 ;

該判斷成立即意味著已經得到kernel32的imageBase00400391 2D 00100000 sub eax, 0x1000 ;

內存中4K對齊,挪動到kernel32 dll的頭部00400396 ^ EB F2 jmp short 0040038A ;

循環得到kernel32 imagebase獲得一個存放kernel32_ImageBase的指針:00400398 50 push eax ; eax == kernel32_ImageBase00400399 E8 C2000000 call 00400460 ; push 0x0040039E0040039E 59 pop ecx0040039F 58 pop eax00400460: 00400460 E8 F5FFFFFF call 0040045A 00400465 0000 add byte ptr [eax], al0040045A: 0040045A 58 pop eax 0040045B 870424 xchg dword ptr [esp], eax 0040045E 50 push eax 0040045F C3 retn進函數時棧佈局$ ==> > 00400465 __CALL_RET_EIP -> EAX$+4 > 0040039E _CALL_RET_EIP -> $+8 > 7C800000 kernel32_ImageBase出函數時棧佈局$ ==> > 0040039E _CALL_RET_EIP$+4 > 00400465 __CALL_RET_EIP$+8 > 7C800000 kernel32.7C800000得出的結論即是,mov ecx,00400465(kernel32_ImageBase),其他忽略不談通過PE結構的固定偏移算出kernel32.dll的導出表,為後面順利取出WINAPI做準備004003A0 8BD8 mov ebx, eax ; ebx == kernel32_ImageBase(SAVE)004003A2 8B48 3C mov ecx, dword ptr [eax+0x3C] ; ecx == e_lfanew(offset)004003A5 03C8 add ecx, eax ; ecx == kernel32_Image_NT_Header004003A7 8B51 78 mov edx, dword ptr [ecx+0x78] ; edx == Kernel32_Export_Table(offset)004003AA 03D0 add edx, eax ;

EDX == Kernel32_ExportTable_VA同上衝定位函數,直接給出結果 mov ecx,00400465004003AC 50 push eax004003AD E8 AE000000 call 00400460004003B2 59 pop ecx004003B3 58 pop eax004003B4 83C1 08 add ecx, 0x8 ; ecx == pNewEipAddr004003B7 50 push eax ; kernel32_ImageBase004003B8 51 push ecx ; ecx == pNewEipAddr004003B9 E8 9C000000 call 0040045A0040045A: 0040045A 58 pop eax 0040045B 870424 xchg dword ptr [esp], eax 0040045E 50 push eax 0040045F C3 retn有意思的在於下面的一句,之前沒注意看,此時才發現&pKernel32 + 8的位置是接下來運算的中的shellcode的一部分004003B4 83C1 08 add ecx, 0x8 ; ecx == 0040046D(pKernel32)004003B7 50 push eax ; kernel32_ImageBase004003B8 51 push ecx ; ecx == pUnKnowAddr004003B9 E8 9C000000 call 0040045A0040046D 59 pop ecx0040046E 58 pop eax ; eax == Kernel32_ImageBase0040046F 8B4A 20 mov ecx, dword ptr [edx+0x20] ; ecx == Kernel32_ExprotTable_AddrOfNames(offset)00400472 52 push edx ; edx == Kernel32_ExportTable_VA00400473 03C1 add eax, ecx ; eax == Kernel32_ExprotTable_AddrOfNames00400475 53 push ebx ; ebx == Kernel32_ImageBase(SAVE)00400476 33DB xor ebx, ebx00400478 EB 04 jmp short 0040047E0040047A 83C0 04 add eax, 0x40040047D 43 inc ebx0040047E 8B0C24 mov ecx, dword ptr [esp] ; ecx == Kernel32_ImageBase00400481 8B10 mov edx, dword ptr [eax] ; api offset00400483 03D1 add edx, ecx ; edx == API Addr00400485 8BFA mov edi, edx ; Sava Api Addr00400487 33C9 xor ecx, ecx00400489 50 push eax ; Kernel32_ExprotTable_AddrOfNames(Save)0040048A 33C0 xor eax, eax0040048C 41 inc ecx ;

計數器(API Name Len)0040048D AE scas byte ptr es:[edi]0040048E ^ 75 FC jnz short 0040048C00400490 49 dec ecx00400491 E8 28FFFFFF call 004003BE004003BE E8 97000000 call 0040045A004003C3 47 inc edi ;

看不懂正常,因為是字符串004003C4 65:74 50 je short 00400417004003C7 72 6F jb short 00400438004003C9 6341 64 arpl word ptr [ecx+0x64], ax004003CC 64:72 65 jb short 00400434004003CF 73 73 jnb short 00400444004003D1 0000 add byte ptr [eax], al004003D3 56 push esi004003D4 6972 74 75616C5>imul esi, dword ptr [edx+0x74], 0x506>004003DB 72 6F jb short 0040044C004003DD 74 65 je short 00400444004003DF 637400 00 arpl word ptr [eax+eax], si004003E3 4D dec ebp004003E4 61 popad004003E5 70 56 jo short 0040043D004003E7 6965 77 4F66466>imul esp, dword ptr [ebp+0x77], 0x694>004003EE 6C ins byte ptr es:[edi], dx004003EF 65:0000 add byte ptr gs:[eax], al004003F2 0043 72 add byte ptr [ebx+0x72], al004003F5 65:61 popad004003F7 74 65 je short 0040045E004003F9 46 inc esi004003FA 696C65 41 00000>imul ebp, dword ptr [ebp+0x41], 0x000400402 0056 69 add byte ptr [esi+0x69], dl00400405 72 74 jb short 0040047B00400407 75 61 jnz short 0040046A00400409 6C ins byte ptr es:[edi], dx0040040A 41 inc ecx0040040B 6C ins byte ptr es:[edi], dx0040040C 6C ins byte ptr es:[edi], dx0040040D 6F outs dx, dword ptr es:[edi]0040040E 6300 arpl word ptr [eax], ax004003C3 47 65 74 50 72 6F 63 41 64 64 72 65 73 73 00 00 GetProcAddress..004003D3 56 69 72 74 75 61 6C 50 72 6F 74 65 63 74 00 00 VirtualProtect..004003E3 4D 61 70 56 69 65 77 4F 66 46 69 6C 65 00 00 00 MapViewOfFile...004003F3 43 72 65 61 74 65 46 69 6C 65 41 00 00 00 00 00 CreateFileA.....00400403 56 69 72 74 75 61 6C 41 6C 6C 6F 63 00 00 00 00 VirtualAlloc....當前在獲取GetProcAddress0040047A 83C0 04 add eax, 0x4 ;

挪動指針,方便取新API0040047D 43 inc ebx ;

計數器0040047E 8B0C24 mov ecx, dword ptr [esp] ;

ecx == Kernel32_ImageBase00400481 8B10 mov edx, dword ptr [eax] ;

api offset00400483 03D1 add edx, ecx ; edx == API Addr00400485 8BFA mov edi, edx ; Sava Api Addr00400487 33C9 xor ecx, ecx00400489 50 push eax ; Kernel32_ExprotTable_AddrOfNames(Save)0040048A 33C0 xor eax, eax0040048C 41 inc ecx ; 計數器(API Name Len)0040048D AE scas byte ptr es:[edi]0040048E ^ 75 FC jnz short 0040048C00400490 49 dec ecx00400491 E8 28FFFFFF call 004003BE00400496 5E pop esi ; esi == "GetProcAddress"00400497 58 pop eax ; eax == Kernel32_ExprotTable_AddrOfNames00400498 8BFA mov edi, edx ; 當前遍歷出的API0040049A F3:A6 repe cmps byte ptr es:[edi], byte ptr>; 比較是否一致0040049C ^ 75 DC jnz short 0040047A ; 不一致開始下一輪0040049E 58 pop eax ; eax == Kernel32_ImageBase0040049F 870424 xchg dword ptr [esp], eax ; 與Kernel32_Export_Table_VA交換004004A2 90 nop004004A3 83C0 1C add eax, 0x1C ; eax == Kernel32_ExportTable_AddrOfFunc(offset)004004A6 8B00 mov eax, dword ptr [eax] ; eax == Kernel32_ExportTable_AddrOfFunc004004A8 50 push eax004004A9 8B4C24 04 mov ecx, dword ptr [esp+0x4] ; ecx == Kernel32_ImageBase004004AD 8BFF mov edi, edi004004AF 58 pop eax004004B0 03C1 add eax, ecx ; eax == Kernel32_ExportTable_AddrOfFunc(VA)004004B2 8B0498 mov eax, dword ptr [eax+ebx*4] ; 利用計數器查表得到API offset004004B5 03C1 add eax, ecx ; 得到API004004B7 50 push eax ; push api addr004004B8 E8 A3FFFFFF call 00400460 ; 執行004004C8 59 pop ecx004004C9 58 pop eax004004CA 83C1 10 add ecx, 0x10 ;

取自定義API名字表中的下一項(VirtualProtect)004004CD 51 push ecx004004CE 8BD0 mov edx, eax004004D0 E8 8BFFFFFF call 00400460004004D5 59 pop ecx004004D6 58 pop eax004004D7 50 push eax ; push lpProcName004004D8 FF31 push dword ptr [ecx] ; hModule004004DA FFD2 call edx ; edx == GetProcAddress004004DC 50 push eax ; api(VirtualProtect) addr004004DD E8 4EFEFFFF call 0040033000400330 8BF8 mov edi, eax00400332 50 push eax00400333 54 push esp00400334 6A 40 push 0x40 ;

VirtualProtect 參數 PAGE_EXECUTE_READWRITE00400336 68 00010000 push 0x100 ; VirtualProtect 參數 Size0040033B E8 F3000000 call 0040043300400436 0000 add byte ptr [eax], al00400438 D4 1A aam 0x1A ; VirtualProtectEx addr0040043A 807C95 B9 80 cmp byte ptr [ebp+edx*4-0x47], 0x80 ; MapViewOfFile addr0040043F 7C 00 jl short 0040044100400350 8B4424 08 mov eax, dword ptr [esp+0x8]00400354 8901 mov dword ptr [ecx], eax ; 保存 kernel32_imagebase00400356 8959 04 mov dword ptr [ecx+0x4], ebx ; 保存GetProcAddress00400359 E8 D5000000 call 004004330040035E 59 pop ecx0040035F C3 retn00400580 59 pop ecx00400581 58 pop eax00400582 50 push eax ; push lpProcName(MapViewOffile)00400583 FF31 push dword ptr [ecx] ; hModule00400585 FF51 04 call dword ptr [ecx+0x4] ; kernel32.GetProcAddress保存了前五字節,應是要進入HOOK:

004005B8 59 pop ecx004005B9 58 pop eax004005BA 83C1 14 add ecx, 0x14004005BD 8B10 mov edx, dword ptr [eax]004005BF 66:8B58 04 mov bx, word ptr [eax+0x4]004005C3 8911 mov dword ptr [ecx], edx004005C5 66:8959 04 mov word ptr [ecx+0x4], bx004005C9 C3 retnHOOK操作:

00400606 59 pop ecx00400607 58 pop eax00400608 C600 68 mov byte ptr [eax], 0x680040060B 8948 01 mov dword ptr [eax+0x1], ecx0040060E C640 05 C3 mov byte ptr [eax+0x5], 0xC300400612 C3 retn恢復環境:00400598 61 popad00400599 830424 07 add dword ptr [esp], 0x70040059D C3 retnCreateFile掛後:7C801A28 > 68 8F074000 push 0x40078F ; ASCII "PQ?"7C801A2D C3 retnMapViewOffile掛後:7C80B995 > 68 38064000 push 0x4006387C80B99A C3 retn如何構造的shellcode已經分析完成,下面看是如何破解的:hook:004007CC 50 push eax004007CD 83C0 75 add eax, 0x75004007D0 B9 16924300 mov ecx, 00439216004007D5 2BC1 sub eax, ecx004007D7 C601 E8 mov byte ptr [ecx], 0xE8004007DA 8941 01 mov dword ptr [ecx+0x1], eax004007DD C741 05 8BCEEBA>mov dword ptr [ecx+0x5], 0xACEBCE8B004007E4 83E9 4D sub ecx, 0x4D004007E7 66:C701 EB4B mov word ptr [ecx], 0x4BEB004007EC 830424 01 add dword ptr [esp], 0x1004007F0 81C1 95220000 add ecx, 0x2295004007F6 C701 33C04083 mov dword ptr [ecx], 0x8340C033004007FC 81C1 D2830000 add ecx, 0x83D200400802 66:C701 C390 mov word ptr [ecx], 0x90C300400807 C3 retn複製代碼Patch Code(只是簡單跟了下,估計不全只簡單跟了下hook createfile的部分,沒測試過):1.004391c9: jmp PatchAddrPatchAddr:

call PatchFun(00400810)恢復原流程: mov ecx, esi jmp 004391CB2.0043B45E |. 8B07 mov eax, dword ptr [edi]0043B460 |. 48 dec eax ; Switch (cases 1..C)0043B461 |. 83F8 0B cmp eax, 0xB0043B464 |. 0F87 95020000 ja 0043B6FF0043B45E |. 33C0 xor eax, eax0043B460 |. 40 inc eax ; Switch (cases 1..C)0043B461 |. 83F8 0B cmp eax, 0xB0043B464 |. 0F87 95020000 ja 0043B6FF3.00443830 . 6A FF push -0x100443830 . C3 retn00443831 ? 90 nopOk 檢測和編譯完成之後可以進入後臺注入這些代碼鎖定ID進行替換或是在安裝APK時進行復蓋,但像這種證件不齊全的也只是能調節在10-20%之間 ,效果並不明顯 調高了反而會觸發後臺告警提示。另外意外的是截獲了部分龍虎的數據,但很可惜被發現了沒能用多久哈


分享到:


相關文章: