找了个样本简单分析下,希望能在看雪继续学习。
PEID打开文件只有两个节 未知~
输入表很少CreateThread ExitProcess Sleep WaitForSingleObject
发现调用了gdi32.dll函数EnumFontsA上网查 是一个例举指定设备可用的字体
user32.dll里的GetDCEx检索指定窗口客户区域或整个屏幕的显示设备上下文环境的句柄,在随后的GDI函数中可以使用该句柄在设备上下文环境中绘图。
用od看看把
001030EF > $ B8 29090000 mov eax, 929
001030F4 . 40 inc eax
001030F5 . B9 58010000 mov ecx, 158
001030FA . BB 3A150000 mov ebx, 153A
001030FF . 40 inc eax
00103100 . 40 inc eax
00103101 . 03C0 add eax, eax
00103103 . 40 inc eax
00103104 . 03C1 add eax, ecx
00103106 . 03C3 add eax, ebx
00103108 . 40 inc eax
00103109 . 40 inc eax
0010310A > C1E8 02 shr eax, 2
0010310D .^ E2 FB loopd short 0010310A
0010310F . 51 push ecx
00103110 . 68 EB2E1000 push 00102EEB
00103115 . 6A 01 push 1 \Flags = DCX_WINDOW
00103117 . 49 dec ecx
00103118 . 50 push eax |hRegionClip = NULL
00103119 . 41 inc ecx
0010311A . 51 push ecx |hWnd = NULL
0010311B . E8 74FDFFFF call 00102E94 Call GetDCEx
00103120 . A3 B9191000 mov dword ptr [1019B9], eax
00103125 .^ E9 6FFDFFFF jmp 00102E99
00102E99 > /B9 C42E1000 mov ecx, 00102EC4
00102E9E . |81E9 C4080000 sub ecx, 8C4
00102EA4 . |51 push ecx lParam = info.00102600
00102EA5 . |68 CD2E1000 push 00102ECD CallbackFunc = info.00102ECD
00102EAA . |FF35 A5191000 push dword ptr [1019A5] FaceName = NULL
00102EB0 . |FF35 B9191000 push dword ptr [1019B9] hDC = 01010058
00102EB6 . |E8 D4FFFFFF call 00102E8F Call EnumFontsA
00102EBB . |B8 00000000 mov eax, 0
00102EC0 . |8BC8 mov ecx, eax
00102EC2 . |8BD1 mov edx, ecx
00102EC4 . |33C0 xor eax, eax
00102EC6 . |50 push eax ; /ExitCode => 0
00102EC7 . |E8 6A020000 call <jmp.&kernel32.ExitProcess> ; \ExitProcess
00102ECC . |C3 retn
00102ECD . |8B4424 10 mov eax, dword ptr [esp+10] EnumFontsA回调函数
00102ED1 . |05 C4080000 add eax, 8C4 清空了102EC4到102ECB的数据
00102ED6 . |C700 90909090 mov dword ptr [eax], 90909090 上面的exitprocess没了,原来是骗人用的
00102EDC . |83C0 04 add eax, 4
00102EDF . |C700 90909090 mov dword ptr [eax], 90909090
00102EE5 . |B8 00000000 mov eax, 0
00102EEA . |C3 retn
00102EEB . /EB 5D jmp short 00102F4A
00102F4A > \90 nop
00102F4B . 90 nop
00102F4C . 90 nop
00102F4D . BB 00000000 mov ebx, 0
00102F52 . B9 04000000 mov ecx, 4
00102F57 > 53 push ebx ; |pThreadParm
00102F58 .^ E2 FD loopd short 00102F57 ; |
00102F5A . 68 992F1000 push 00102F99 ; |ThreadFunction = info.00102F99
00102F5F . 53 push ebx ; |StackSize
00102F60 . 53 push ebx ; |pSecurity
00102F61 . E8 CA010000 call <jmp.&kernel32.CreateThread> ; \CreateThread
00102F66 . A3 A1191000 mov dword ptr [1019A1], eax
00102F6B . BB 00000000 mov ebx, 0
00102F70 . 53 push ebx
00102F71 . 53 push ebx ; /pThreadId => NULL
00102F72 . 53 push ebx ; |CreationFlags => 0
00102F73 . 53 push ebx ; |pThreadParm => NULL
00102F74 . 68 DF2F1000 push 00102FDF ; |ThreadFunction = info.00102FDF
00102F79 . 53 push ebx ; |StackSize => 0
00102F7A . 53 push ebx ; |pSecurity => NULL
00102F7B . E8 B0010000 call <jmp.&kernel32.CreateThread> ; \CreateThread
00102F80 . A3 A5191000 mov dword ptr [1019A5], eax
00102F85 . A1 A1191000 mov eax, dword ptr [1019A1]
00102F8A . 6A FF push -1 ; /Timeout = INFINITE
00102F8C . 50 push eax ; |hObject => NULL
00102F8D . E8 B0010000 call <jmp.&kernel32.WaitForSingleObje>; \WaitForSingleObject
00102F92 . 6A 00 push 0 ; /ExitCode = 0
00102F94 . E8 9D010000 call <jmp.&kernel32.ExitProcess> ; \ExitProcess
102F99:
00102F99 8B35 B1191000 mov esi, dword ptr [1019B1] ; info.0010130C 看来这个地址很重要~
00102F9F 8B0D B5191000 mov ecx, dword ptr [1019B5] 0x691这个数是干啥用的?一般都是次数~~
00102FA5 56 push esi
00102FA6 8BF1 mov esi, ecx
00102FA8 56 push esi
00102FA9 6A 01 push 1
00102FAB E8 8C010000 call <jmp.&kernel32.Sleep>
00102FB0 833D AD191000 0>cmp dword ptr [1019AD], 2 1019ad里面存数值来判断是否线程继续执行下去~
00102FB7 ^ 75 F0 jnz short 00102FA9 如果 不是2,那就处于无限的sleep 1ms了
00102FB9 EB 15 jmp short 00102FD0 初始为2跳到102fd0
00102FD0 59 pop ecx 0x691要做动作了~
00102FD1 5E pop esi 0010130c(8c9b66f4)
00102FD2 A1 A9191000 mov eax, dword ptr [1019A9] eax:674E8cEB
00102FD7 8A1E mov bl, byte ptr [esi] 取出f4
00102FD9 32D8 xor bl, al 与67异或 EBX:1f
00102FDB 881E mov byte ptr [esi], bl 结果存到esi:0010130c中
00102FDD ^ EB DC jmp short 00102FBB
00102FBB 46 inc esi esi+1 0010130D
00102FBC 50 push eax
00102FBD B8 AD191000 mov eax, 001019AD
00102FC2 C700 00000000 mov dword ptr [eax], 0 更该了线程的执行条件,为0。
00102FC8 58 pop eax
00102FC9 ^ E2 DA loopd short 00102FA5 看来要执行0x691次
00102FCB ^ E9 61E9FFFF jmp 00101931 回到sleep了!因为之前更改了。所以一直在sleep,估计下面的线程会更改这个值
00102FDF B8 01000000 mov eax, 1
00102FE4 A3 AD191000 mov dword ptr [1019AD], eax 更改了上面线程的执行条件~1019ad:1
00102FE9 68 A9191000 push 001019A9 这个是上个线程用来解密用的~
00102FEE EB 02 jmp short 00102FF2
00102FF2 E8 F6FEFFFF call 00102EED 这个函数~
00102EED 59 pop ecx
00102EEE 5A pop edx
00102EEF 51 push ecx
00102EF0 A1 9D191000 mov eax, dword ptr [10199D] 10199d:eb674e8c这个跟1019A9的正好相反
00102EF5 EB 18 jmp short 00102F0F
00102F0F 8BC8 mov ecx, eax ecx:EB674E8C
00102F11 D1E0 shl eax, 1 左移1位D6CE9D18
00102F13 D1E0 shl eax, 1 继续左移AD9D3A30
00102F15 D1C0 rol eax, 1 左移,把最高位放到最低位:5B3A7461
00102F17 83E0 FA and eax, FFFFFFFA 和FFFFFFFA与运算 :5B3A7460
00102F1A ^ EB DD jmp short 00102EF9
00102EF9 83E0 FD and eax, FFFFFFFD 和FFFFFFFD与运算 两个与运算就是把二进制位的最后三位清零
00102EFC 33C1 xor eax, ecx 再和之前的自己异或运算:B05D3AEC
00102EFE 05 BD040000 add eax, 4BD +4BD :B05D3FA9
00102F03 A3 9D191000 mov dword ptr [10199D], eax 在放回去~~
00102F08 C1C8 10 ror eax, 10 右移,跟rol相反,这条指令就是低16位与高16位交换位置
00102F0B EB 0F jmp short 00102F1C ~3FA9B05D
00102F1C C1C8 04 ror eax, 4 上面说过着指令了,就不在看了。
00102F1F C1C8 02 ror eax, 2
00102F22 C1C8 02 ror eax, 2 5D3FA9B0
00102F25 8902 mov dword ptr [edx], eax edx:001019A9 更改了上个线程的密钥
00102F27 83C2 04 add edx, 4
00102F2A C702 02000000 mov dword ptr [edx], 2 edx:001019ad 更该了上个线程的执行条件
00102F30 C3 retn
00102FDF B8 01000000 mov eax, 1
00102FE4 A3 AD191000 mov dword ptr [1019AD], eax
00102FE9 68 A9191000 push 001019A9
00102FEE EB 02 jmp short 00102FF2
00102FF0 40 inc eax
00102FF1 43 inc ebx
00102FF2 E8 F6FEFFFF call 00102EED
00102FF7 6A 01 push 1
00102FF9 E8 3E010000 call <jmp.&kernel32.Sleep> 又开始sleep了
00102FFE 833D AD191000 0>cmp dword ptr [1019AD], 0 原来也是这个条件,判断是否为0,为0就改变为1,然后去算密钥
00103005 ^ 74 D8 je short 00102FDF
00103007 ^ EB EE jmp short 00102FF7 无限sleep了
00101931 E8 87FEFFFF call 001017BD
00101936 68 3E131000 push 0010133E ; ASCII "sfe34sde3"
0010193B 6A 00 push 0
0010193D 6A 01 push 1
0010193F 6A 00 push 0
00101941 E8 DFFFFFFF call 00101925
00101946 83F8 00 cmp eax, 0
00101949 74 19 je short 00101964
0010194B E8 DBFFFFFF call 0010192B
00101950 83F8 00 cmp eax, 0
00101953 75 0F jnz short 00101964
00101955 E8 D6FCFFFF call 00101630
0010195A E8 0BFAFFFF call 0010136A
0010195F E8 32FAFFFF call 00101396
00101964 6A 00 push 0
00101966 E8 78FFFFFF call 001018E3
0010196B 0000 add byte ptr [eax], al
0010196D 0000 add byte ptr [eax], al
0010196F 0000 add byte ptr [eax], al
001017BD 56 push esi
001017BE 57 push edi
001017BF 51 push ecx
001017C0 53 push ebx
001017C1 52 push edx
001017C2 B8 00000000 mov eax, 0
001017C7 83C0 20 add eax, 20
001017CA 83C0 10 add eax, 10
001017CD 64:8B00 mov eax, dword ptr fs:[eax] TEB结构的0x30偏移处是PEB
001017D0 8B40 0C mov eax, dword ptr [eax+C] PEB的0x0c处指向PEB_LDR_DATA
001017D3 8B70 1C mov esi, dword ptr [eax+1C] InInitializationOrderModuleList
001017D6 AD lods dword ptr [esi]
001017D7 8B40 08 mov eax, dword ptr [eax+8] kernel32的基址
001017DA A3 AC171000 mov dword ptr [1017AC], eax
001017DF BA 1A171000 mov edx, 0010171A ; ASCII "GetProcAddress"
001017E4 8BD8 mov ebx, eax
001017E6 8B73 3C mov esi, dword ptr [ebx+3C] kernel32的PE头偏移
001017E9 8B7433 78 mov esi, dword ptr [ebx+esi+78]
001017ED 03F3 add esi, ebx 输出表
001017EF 8B7E 20 mov edi, dword ptr [esi+20]
001017F2 03FB add edi, ebx AddressOfFunction的RVA
001017F4 8B4E 14 mov ecx, dword ptr [esi+14] AddressOfFunction的条目数量
001017F7 33ED xor ebp, ebp
001017F9 56 push esi
001017FA 57 push edi
001017FB 51 push ecx
001017FC 8B3F mov edi, dword ptr [edi]
001017FE 03FB add edi, ebx AddressOfFunction的第一个元素
00101800 8BF2 mov esi, edx
00101802 6A 0E push 0E
00101804 59 pop ecx
00101805 F3:A6 repe cmps byte ptr es:[edi], byte ptr>
00101807 74 08 je short 00101811
00101809 59 pop ecx
0010180A 5F pop edi
0010180B 83C7 04 add edi, 4
0010180E 45 inc ebp
0010180F ^ E2 E9 loopd short 001017FA AddressOfFunction中查找GetProcAddress
00101811 59 pop ecx
00101812 5F pop edi
00101813 5E pop esi
00101814 8BCD mov ecx, ebp
00101816 8B46 24 mov eax, dword ptr [esi+24] AddressOfNameOrdinals
00101819 03C3 add eax, ebx
0010181B D1E1 shl ecx, 1
0010181D 03C1 add eax, ecx
0010181F 33C9 xor ecx, ecx
00101821 66:8B08 mov cx, word ptr [eax]
00101824 8B46 1C mov eax, dword ptr [esi+1C]
00101827 03C3 add eax, ebx
00101829 C1E1 02 shl ecx, 2
0010182C 03C1 add eax, ecx
0010182E 8B00 mov eax, dword ptr [eax]
00101830 03C3 add eax, ebx eax:GetProcAddress基址
00101832 A3 90171000 mov dword ptr [101790], eax
00101837 68 0B171000 push 0010170B ; ASCII "LoadLibraryExA"
0010183C FF35 AC171000 push dword ptr [1017AC]
00101842 E8 B4000000 call 001018FB
00101847 A3 8C171000 mov dword ptr [10178C], eax
0010184C 6A 00 push 0
0010184E 6A 00 push 0
00101850 68 54161000 push 00101654 ; ASCII "ws2_32.dll"
00101855 FFD0 call eax eax:"LoadLibraryExA",
00101857 A3 A7161000 mov dword ptr [1016A7], eax 去load ws2_32.dll 1016a7:ws2_32.dll基址
0010185C 8BD8 mov ebx, eax
0010185E BE 5F161000 mov esi, 0010165F ; ASCII "socket"
00101863 BF AB161000 mov edi, 001016AB
00101868 E8 2A000000 call 00101897
00101897 4E dec esi
00101898 46 inc esi
00101899 803E 00 cmp byte ptr [esi], 0 判断参数 函数名是否为空
0010189C 74 14 je short 001018B2
0010189E 56 push esi
0010189F 53 push ebx
001018A0 E8 56000000 call 001018FB ; jmp 到 kernel32.GetProcAddress
001018A5 8907 mov dword ptr [edi], eax
001018A7 83C7 04 add edi, 4
001018AA 46 inc esi
001018AB 803E 00 cmp byte ptr [esi], 0
001018AE ^ 74 E8 je short 00101898
001018B0 ^ EB F8 jmp short 001018AA
001018B2 C3 retn
0010186D 6A 00 push 0
0010186F 6A 00 push 0
00101871 68 B0171000 push 001017B0 ; ASCII "kernel32.dll"
00101876 E8 7A000000 call 001018F5 ; jmp 到 kernel32.LoadLibraryExA
0010187B A3 AC171000 mov dword ptr [1017AC], eax
00101880 8BD8 mov ebx, eax
00101882 BE CB161000 mov esi, 001016CB ; ASCII "ExitProcess"
00101887 BF 78171000 mov edi, 00101778
0010188C E8 06000000 call 00101897
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)