能力值:
( LV4,RANK:50 )
3 楼
由于无发再次发贴,因此我只好在自已的贴里编辑贴,以使能有更多的信息可见.更有可能得到各位大大的回复.
独占模式程序调试
学习对象: StarCraft 1.08 (以下简称SC)
学习目标: 将其由全屏独占模式更改为窗口模式
工具: OllyDBG(下载中心当的OllyICE).
另:跟踪过程中发现SC还加载了其目录下后缀为SNP的模块作网络通讯用,但时机还未知.
解决办法:
1.SetCooperativeLevel
004DEAE8 6A 08 push 13
004DEAEA |. 52 push edx
004DEAEB |. 8B08 mov ecx, dword ptr [eax]
004DEAED |. 50 push eax
004DEAEE |. FF51 50 call dword ptr [ecx+50] ; <ddraw.SetCooperativeLevel>
将指令push 13换为push 8 ( DDSCL_ALLOWREBOOT|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN --> DDSCL_NORMAL)
2.SetDisplayMode(注意,有两处调用,另外在处理后还需修改调色版,可以用加区段的办法)
004DEB48 |. 6A 08 push 8
004DEB4A |. 50 push eax
004DEB4B |. 8B11 mov edx, dword ptr [ecx]
004DEB4D |. 57 push edi
004DEB4E |. 51 push ecx
004DEB4F |. FF52 54 call dword ptr [edx+54]; 这里是SetDislayMode
将此调用换为xor eax,eax
其它的NOP掉.
能力值:
( LV4,RANK:50 )
4 楼
;作者:CNBlastMAN
;函数功能:计算检验字
;参数: ecx =>数据缓冲指针 edx =>数据长度
;返回: ax =>校验字
0BAA20E0 > 51 push ecx ; 保护ecx //函数功能:计算检验字
0BAA20E1 56 push esi ; 保护esi
0BAA20E2 83C2 FE add edx, -2 ; edx=edx-2; //edx保存的是长度
0BAA20E5 83C1 02 add ecx, 2 ; ecx=ecx+2; //ecx指向数据开始第三个字节
0BAA20E8 E8 53EFFFFF call <求和取余> ; 求和取余
0BAA20ED 25 FFFF0000 and eax, 0FFFF ; eax=eax&0xffff; //eax=LOWORD(<求和取余>函数的返回值)
0BAA20F2 B9 FF000000 mov ecx, 0FF ; ecx=0xff; //ecx=255
0BAA20F7 8BF0 mov esi, eax ; esi=eax; //将<求和取余>的结果保存到esi
0BAA20F9 25 FF000000 and eax, 0FF ; eax=LOBYTE(LOWORD(eax));
0BAA20FE C1EE 08 shr esi, 8 ; esi=esi>>8; //esi=HIBYTE(LOWORD(esi)),shr,补0
0BAA2101 03C6 add eax, esi ; eax=eax+esi; //eax=LOBYTE(LOWORD(eax))+HIBYTE(LOWORD(esi))
0BAA2103 99 cdq ; 除法准备; //用eax的符号位填充edx的所有位
0BAA2104 F7F9 idiv ecx ; eax=eax/255,edx=eax%255;
0BAA2106 0AC1 or al, cl ; al=0xff; //al=al|cl = 0x00|0xff ===> al=LOBYTE(AX)|LOBYTE(CX)
0BAA2108 2AC2 sub al, dl ; al=al-dl; //al=0xff-余数 (al=0xff-dl)
0BAA210A 884424 04 mov byte ptr [esp+4], al ; //这里其实破坏了堆栈中的数据,不知道是不是故意这么做的.
0BAA210E 8B4C24 04 mov ecx, dword ptr [esp+4] ; //
0BAA2112 81E1 FF000000 and ecx, 0FF ; ecx=al;
0BAA2118 8D0431 lea eax, dword ptr [ecx+esi] ; eax=al+esi;
0BAA211B BE FF000000 mov esi, 0FF ; esi=0xff;
0BAA2120 99 cdq ; 除法准备; //用eax的符号位填充edx的所有位
0BAA2121 F7FE idiv esi ; eax=eax/255,edx=eax%255;
0BAA2123 C1E1 08 shl ecx, 8 ; ecx=ecx<<8; //shl,补0
0BAA2126 0C FF or al, 0FF ; al=0xff;
0BAA2128 2AC2 sub al, dl ; al=al-dl; //见上一个对此语句的说明
0BAA212A 23C6 and eax, esi ; eax=eax&0xff; //eax=eax&esi ==>eax=LOBYTE(LOWORD(eax)
0BAA212C 5E pop esi ; 恢复esi
0BAA212D 0BC1 or eax, ecx ; eax=eax|ecx; //RetVal=eax,由上面的处理来看,相当于eax=MAKEWORD(ch,al)
0BAA212F 59 pop ecx ; 恢复ecx
0BAA2130 C3 retn
;函数功能:求和取余:
0BAA1040 > 53 push ebx ; 保护ebx; //函数功能:求和取余
0BAA1041 56 push esi ; 保护esi
0BAA1042 33DB xor ebx, ebx ; ebx=0;
0BAA1044 33F6 xor esi, esi ; esi=0;
0BAA1046 8D4C11 FF lea ecx, dword ptr [ecx+edx-1] ; ecx=ecx+edx-1; //ecx指向数据尾部字节,表达式中ecx为数据起始地址,edx=12 =>数据长度(14)-2
0BAA104A 8BC2 mov eax, edx ; eax=edx; //eax=数据长度
0BAA104C 4A dec edx ; edx--;
0BAA104D 85C0 test eax, eax
0BAA104F 74 1F je short 0BAA1070 ; if(eax==0) jmp 0BAA1070 //没有数据处理则跳转
0BAA1051 57 push edi ; else{ //变量保护
0BAA1052 8D7A 01 lea edi, dword ptr [edx+1] ; edi=edx+1; //edi=eax=数据长度
0BAA1055 33D2 xor edx, edx ; do{ edx=0; //此循环将数据的字节从尾部开始相加,当大于255时取大于部分累加成和,并保存到ecx,一直处理到缓冲的第3个字节为止,也就是此函数开始指所提供的ecx
0BAA1057 8A11 mov dl, byte ptr [ecx] ; dl=(byte)*ecx; //dl=数据尾部字节
0BAA1059 03DA add ebx, edx ; ebx=ebx+dl; //ebx=ebx+数据尾部字节的值
0BAA105B 49 dec ecx ; ecx=ecx-1; //ecx向数据首部方向移动一字节
0BAA105C 81FB FF000000 cmp ebx, 0FF ; if(ebx>=255) ebx-=255;
0BAA1062 72 06 jb short 0BAA106A ; //
0BAA1064 81EB FF000000 sub ebx, 0FF ; //endif
0BAA106A 03F3 add esi, ebx ; esi=esi+ebx;
0BAA106C 4F dec edi ; edi--;
0BAA106D ^ 75 E6 jnz short 0BAA1055 ; }while(edi==0);
0BAA106F 5F pop edi ; 恢复edi
0BAA1070 8BC6 mov eax, esi ; eax=esi; //加的结果保存到eax
0BAA1072 33D2 xor edx, edx ; edx=0;
0BAA1074 B9 FF000000 mov ecx, 0FF ; ecx=0xff; //ecx=255
0BAA1079 5E pop esi ; 恢复esi
0BAA107A F7F1 div ecx ; eax=eax/255,edx=eax%255;
0BAA107C 33C0 xor eax, eax ; eax=0
0BAA107E 8AC2 mov al, dl ; al=dl; //al=和的结果除以255的余数
0BAA1080 8AE3 mov ah, bl ; ah=bl; //bl=字节总和除以255的余(看上面的循环)
0BAA1082 5B pop ebx
0BAA1083 C3 retn ; 返回eax; //eax=MAKEWORD(bl,dl)
能力值:
( LV4,RANK:50 )
6 楼
下午又跑了N次.给自己留点东西:
1.关于同步对象(如事件或临界变量)的下断注意事项.
多线程程序中(现在基本不考虑单线程程序的存在了,如了部分壳的解码程序)
如果下断函数WaitXXX,大多数情况下会导致目标程序崩溃.
必须断在WaitXXX函数被调用之后,对临界区来说,就是EnterXXX.
2.send/recv被调用后,不要在其使用的缓冲上下访问断点,除非你已经清楚的知道目标程序所使用的通信模型是阻塞模型,而且在处理完该缓冲之前不会被投递到核心态事务,否则会使OD非法跳出.注:OD是一个用户级调试器.
3.尽可能的在某个函数上下断之前先读一下该函数的代码.根据其调用的外部函数和结构判断其功能,并在确定功能之后为其编辑标签.
4.[壳相关]
粗跟壳的时候,在步过时会产生异常的地方,使用步入多半不会抛异常.
一般比较牛的壳,在跟得比较深入了的时候,除了非常熟悉的壳,千万不要用ALT+F9,否则之前的东西会付之流水...
[天黑了]
读Themida的解码代码(不知道版本,也不知道其是否使用驱动).跳来跳去的头都晕了.先F8了一遍.除了会产生异常的地方,其它我都F8了.我现在的水平要研究这个无疑是大海捞针.不过跟了总是有益无害嘛.纯粹属于娱乐性质..
开个玩笑.只要你有时间,F7才是天下最牛的武器...呵
1.有一段解壳执行代码,将每个字节减1,总共7000h个字节,处理完后跳到处理后的代码执行(类似的有好几处).
00960354 FE0F dec byte ptr [edi] ; 还原后面要运行的指令,0096035A处开始,大小(7000h),每个字节减1
00960356 47 inc edi
00960357 49 dec ecx
00960358 ^ 75 FA jnz short 00960354
执行到这里的时候需要步入,否则会抛出异常,所以用F7:
00960388 E8 03000000 call 00960390
//-------------------跟进去后会用到下面这段代码.
009603DD 8BCA mov ecx, edx ; ecx=UPX段偏移
009603DF 33FF xor edi, edi
009603E1 66:8138 4D5A cmp word ptr [eax], 5A4D ; 比较MZ标志,跳到模块头部
009603E6 75 0E jnz short 009603F6
009603E8 0FB750 3C movzx edx, word ptr [eax+3C]
009603EC 03D0 add edx, eax
009603EE 813A 50450000 cmp dword ptr [edx], 4550
009603F4 74 08 je short 009603FE
009603F6 2D 00100000 sub eax, 1000
009603FB 47 inc edi
009603FC ^ EB E3 jmp short 009603E1
009603FE 64:8F05 0000000>pop dword ptr fs:[0] ; 设置异常处理程序
00960405 83C4 04 add esp, 4
00960408 8D95 87378206 lea edx, dword ptr [ebp+6823787]
0096040E 52 push edx
0096040F 64:FF35 0000000>push dword ptr fs:[0] ; 保存异常处理,替换为ESP中的值
00960416 64:8925 0000000>mov dword ptr fs:[0], esp ; 替换异常处理=0012ffe0
0096041D 03C1 add eax, ecx ; 文件基址+UPX段偏移
0096041F 2D 00100000 sub eax, 1000 ; eax=CreateFileA函数地址,准备驱动解码,注:CreateFileA存放于 UPX段地址+1000处(是UPX段地址而不是UPX段偏移)
00960424 8B70 04 mov esi, dword ptr [eax+4] ; esi=ExitProcess
00960427 81E6 0000FFFF and esi, FFFF0000 ; esi=Kernel32的模块基址+10000h
0096042D 81FE 00000080 cmp esi, 80000000
00960433 76 03 jbe short 00960438
00960435 8B70 1C mov esi, dword ptr [eax+1C]
00960438 33C0 xor eax, eax ; eax清0,作为计数,准备取模块基址
0096043A 83F8 32 cmp eax, 32 ; 计数eax等于32次,则跳转
0096043D 74 1F je short 0096045E
0096043F 66:813E 4D5A cmp word ptr [esi], 5A4D ; 比较esi是否模块基址
00960444 74 09 je short 0096044F ; 是则跳转
00960446 81EE 00000100 sub esi, 10000 ; 不是则将esi-10000
0096044C 40 inc eax ; 计数eax+1
0096044D ^ EB EB jmp short 0096043A
0096044F 8B7E 3C mov edi, dword ptr [esi+3C] ; 已取到模块基址,edi=PE头偏移
00960452 03FE add edi, esi ; edi=edi+esi; //edi=PE头地址
00960454 813F 50450000 cmp dword ptr [edi], 4550 ; 取PE头的标志字与"PE"比较,验证是否正确的PE头
0096045A 74 44 je short 009604A0 ; 是则跳转下一个处理(009604A0),否则重新取模块基址 009604A0 96 xchg eax, esi ; PE头正确,设置ecx=eax,eax=模块基址
009604A1 64:8F05 0000000>pop dword ptr fs:[0] ; 恢复异常处理
2.在跟到大概八九个VirtualAlloc(,,,40(EXECUTE_READWRITE))的调用后(马上就要正式解码了,可惜不小心F8跑飞了..),于是点支烟,直接Ctrl+F2...
//---------------------------------------------------
来了回一直F7(我纯粹是找死)..发现这段被执行了N次(要睡了,跟到这里有点犯困,来不及写注释,有点想放弃了):
00960205 55 push ebp
00960206 8BEC mov ebp, esp
00960208 81C4 7CFFFFFF add esp, -84
0096020E 60 pushad
0096020F E8 00000000 call 00960214
00960214 5A pop edx
00960215 81EA 1E358206 sub edx, 682351E
0096021B 8D45 80 lea eax, dword ptr [ebp-80]
0096021E 8B5D 08 mov ebx, dword ptr [ebp+8]
00960221 C785 7CFFFFFF 0>mov dword ptr [ebp-84], 0
0096022B 8B8D 7CFFFFFF mov ecx, dword ptr [ebp-84]
00960231 D1C3 rol ebx, 1
00960233 8818 mov byte ptr [eax], bl
00960235 41 inc ecx
00960236 898D 7CFFFFFF mov dword ptr [ebp-84], ecx
0096023C 81BD 7CFFFFFF 8>cmp dword ptr [ebp-84], 80
00960246 ^ 75 E3 jnz short 0096022B
00960248 C785 7CFFFFFF 0>mov dword ptr [ebp-84], 0
00960252 8DBA 3F348206 lea edi, dword ptr [edx+682343F]
00960258 8D75 80 lea esi, dword ptr [ebp-80]
0096025B 8A0E mov cl, byte ptr [esi]
0096025D BB F4010000 mov ebx, 1F4
00960262 B8 AB375478 mov eax, 785437AB
00960267 D3D0 rcl eax, cl
00960269 8A0F mov cl, byte ptr [edi]
0096026B D3D0 rcl eax, cl
0096026D 4B dec ebx
0096026E ^ 75 F7 jnz short 00960267
00960270 0FAFC3 imul eax, ebx
00960273 47 inc edi
00960274 46 inc esi
00960275 8B8D 7CFFFFFF mov ecx, dword ptr [ebp-84]
0096027B 41 inc ecx
0096027C 898D 7CFFFFFF mov dword ptr [ebp-84], ecx
00960282 81F9 80000000 cmp ecx, 80
00960288 ^ 75 D1 jnz short 0096025B
0096028A 61 popad
0096028B C9 leave
0096028C C2 0400 retn 4