• 标 题:UltraEdit-32 10.20版脱壳记
  • 作 者:fxyang
  • 时 间:004-04-29,00:06
  • 链 接:http://bbs.pediy.com

UltraEdit-32 10.20版使用了Armadillo壳的CC技术,但是没有用到远地址jmp和IAT表乱序排列。所以比较简单些。

1.得到程序的正确代码:
   由于没有使用远地址jmp和iat表远地址存放技术,所以就可以直接LordPE的ArmDump插件dump下。
   由于dump时程序运行过了,所以这时的临时data段有了垃圾数据,必须重新得到这个段的初始数据,不然运行就会出错
方法如下:
  跟踪发现是data段00595000开始 长度5000的段有错误。根据这个线索
   
  BP OpenMutexA 
  然后按正常的方法(不用说了吧)
  完成双进程到单进程的转换后
  bp VirtualProtect  后F9运行程序,中断后再按4次F9(只能四次)并且注意堆栈中的这个函数调用地址,因为第5次就到
了壳的子进程中了。Ctrl+F9返回再Ctrl+F9一次来到这里:


005FAE71   >ADD ESP,4                  <--返回
005FAE74   >MOV DWORD PTR SS:[EBP-54],EAX
005FAE77   >CMP DWORD PTR SS:[EBP-54],0
005FAE7B   >JNZ SHORT Uedit320.005FAE84
005FAE7D   >XOR EAX,EAX
005FAE7F   >JMP Uedit320.005FB03C
005FAE84   >PUSH 0
005FAE86   >PUSH 1
005FAE88   >MOV EDX,DWORD PTR DS:[62C4F8]
005FAE8E   >PUSH EDX
005FAE8F   >CALL DWORD PTR DS:[62C4FC]  <--这里进入壳的子进程地址,F7进入
005FAE95   >TEST EAX,EAX
005FAE97   >JNZ SHORT Uedit320.005FAEAA
005FAE99   >MOV DWORD PTR DS:[62C504],5
005FAEA3   >XOR EAX,EAX
005FAEA5   >JMP Uedit320.005FB03C

进入后来到这里:

00DDAA1B   >PUSH EBP
00DDAA1C   >MOV EBP,ESP
00DDAA1E   >PUSH EBX
00DDAA1F   >MOV EBX,DWORD PTR SS:[EBP+8]
00DDAA22   >PUSH ESI
00DDAA23   >MOV ESI,DWORD PTR SS:[EBP+C]
00DDAA26   >PUSH EDI
00DDAA27   >MOV EDI,DWORD PTR SS:[EBP+10]
00DDAA2A   >TEST ESI,ESI
00DDAA2C   >JNZ SHORT 00DDAA37
00DDAA2E   >CMP DWORD PTR DS:[DEA9F4],0
00DDAA35   >JMP SHORT 00DDAA5D

这里Ctrl+S打开搜索窗口输入:

PUSH EBP 
MOV EBP,ESP 
PUSH ECX 
PUSH EBX 
XOR EBX,EBX

(这是第一个anti的地方的特征代码)
来到这里:

00DD7D72   >PUSH EBP              
00DD7D73   >MOV EBP,ESP
00DD7D75   >PUSH ECX
00DD7D76   >PUSH EBX
00DD7D77   >XOR EBX,EBX               //特征代码
00DD7D79   >CMP BYTE PTR DS:[DE9075],BL
00DD7D7F   >PUSH ESI
00DD7D80   >PUSH EDI
00DD7D81   >JNZ SHORT 00DD7D94
00DD7D83   >CMP BYTE PTR DS:[DE8CB1],BL
00DD7D89   >JNZ SHORT 00DD7D94
00DD7D8B   >CALL 00DB72E9            <--第一个anti函数
00DD7D90   >TEST EAX,EAX             <--函数返回值,必须修改为0
00DD7D92   >JNZ SHORT 00DD7D9B
00DD7D94   >XOR AL,AL
00DD7D96   >JMP 00DD7EC7

过了第一个anti后,bp VirtualAlloc 这时要仔细的看看堆栈中函数调用的地址,F9运行二次,Alt+F9返回
取消原来的断点后bp memcpy F9运行中断后检查堆栈中的第一个参数,如果变成了远地址(不是壳的子进程的地址)
如:0012BABC   01570020  |dest = 01570020  <--这个
就Alt+F9返回到壳的子进程中,Cltr+F9来到:

00DD34C8    >PUSH EAX
00DD34C9    >PUSH DWORD PTR SS:[EBP-1A1C]
00DD34CF    >PUSH DWORD PTR DS:[DE9090]               ; Uedit320.0066CCE6
00DD34D5    >CALL 00DB76C8
00DD34DA    >ADD ESP,14                             //返回地址,下面快到复制代码的地方了。
00DD34DD    >MOV DWORD PTR DS:[DE9090],EAX
00DD34E2    >CMP DWORD PTR DS:[DE9090],0
00DD34E9    >JNZ SHORT 00DD350C
00DD34EB    >MOV EAX,DWORD PTR SS:[EBP+8]
00DD34EE    >MOV EAX,DWORD PTR DS:[EAX]
00DD34F0    >AND DWORD PTR DS:[EAX],0
00DD34F3    >PUSH 0DE1A38                             ; ASCII "Location ES1"
00DD34F8    >MOV EAX,DWORD PTR SS:[EBP+8]
00DD34FB    >PUSH DWORD PTR DS:[EAX+4]
00DD34FE    >CALL 00DDA90C                            ; JMP to msvcrt.strcpy


向下看看:

00DD3692   >ADD EAX,DWORD PTR SS:[EBP-1A2C]
00DD3698   >MOV ECX,DWORD PTR SS:[EBP-1A48]
00DD369E   >SUB ECX,EAX
00DD36A0   >MOV DWORD PTR SS:[EBP-1A4C],ECX
00DD36A6   >MOV EAX,DWORD PTR DS:[DE9560]
00DD36AB   >MOV AL,BYTE PTR DS:[EAX+3D2F]
00DD36B1   >MOV BYTE PTR SS:[EBP-31AC],AL
00DD36B7   >MOVZX EAX,BYTE PTR SS:[EBP-31AC]
00DD36BE   >TEST EAX,EAX
00DD36C0   >JE SHORT 00DD36DE
00DD36C2   >MOV EAX,DWORD PTR SS:[EBP-1A44]
00DD36C8   >XOR EAX,DWORD PTR SS:[EBP-1A3C]
00DD36CE   >MOV ECX,DWORD PTR SS:[EBP-1A24]
00DD36D4   >ADD ECX,DWORD PTR SS:[EBP-1A4C]
00DD36DA   >MOV DWORD PTR DS:[ECX],EAX
00DD36DC   >JMP SHORT 00DD36F2                  //*********
00DD36DE   >MOV EAX,DWORD PTR SS:[EBP-1A24]
00DD36E4   >ADD EAX,DWORD PTR SS:[EBP-1A4C]
00DD36EA   >MOV ECX,DWORD PTR SS:[EBP-1A44]
00DD36F0   >MOV DWORD PTR DS:[EAX],ECX
00DD36F2   >JMP SHORT 00DD3702                 //***********
00DD36F4   >MOV EAX,DWORD PTR SS:[EBP-1A48]
00DD36FA   >MOV ECX,DWORD PTR SS:[EBP-1A44]
00DD3700   >MOV DWORD PTR DS:[EAX],ECX
00DD3702  ^>JMP 00DD3611                        //**********          
00DD3707   >MOV EAX,DWORD PTR DS:[DE9560]      //这三个jmp是特征代码
00DD370C   >MOV AL,BYTE PTR DS:[EAX+3D2F]
00DD3712   >MOV BYTE PTR SS:[EBP-31B0],AL
00DD3718   >MOVZX EAX,BYTE PTR SS:[EBP-31B0]   <--第二个anti的地方,修改下面的EAX值为0
00DD371F   >TEST EAX,EAX
00DD3721   >JE 00DD3851


修改后再看看下面就是复制代码到程序中的段了:

00DD38B9  CALL DWORD PTR DS:[DDB138]               ; kernel32.VirtualProtect  //设置段的属性为可读写
00DD38BF  PUSH DWORD PTR SS:[EBP-1A28]
00DD38C5  PUSH DWORD PTR SS:[EBP-1A24]
00DD38CB  MOV EAX,DWORD PTR SS:[EBP-18E8]              
00DD38D1  ADD EAX,DWORD PTR SS:[EBP-1A2C]
00DD38D7  PUSH EAX                                 <--复制到的段基地址  //注意这里
00DD38D8  CALL 00DDA8B2                            ; JMP to msvcrt.memcpy  //复制函数
00DD38DD  ADD ESP,0C
00DD38E0  LEA EAX,DWORD PTR SS:[EBP-1A30]
00DD38E6  PUSH EAX
00DD38E7  PUSH DWORD PTR SS:[EBP-1A30]
00DD38ED  PUSH DWORD PTR SS:[EBP-1A28]
00DD38F3  MOV EAX,DWORD PTR SS:[EBP-18E8]
00DD38F9  ADD EAX,DWORD PTR SS:[EBP-1A2C]
00DD38FF  PUSH EAX
00DD3900  CALL DWORD PTR DS:[DDB138]               ; kernel32.VirtualProtect   //重新设置段的属性为只读
00DD3906  MOV EAX,DWORD PTR SS:[EBP-1A24]
00DD390C  MOV DWORD PTR SS:[EBP-2FF8],EAX
00DD3912  PUSH DWORD PTR SS:[EBP-2FF8]
00DD3918  CALL 00DDA8AC                            ; JMP to msvcrt.??3@YAXPAX@Z
00DD391D  POP ECX
00DD391E  JMP 00DD33C9

说明:如果是3.60版之前的可以在这里得到程序的代码,因为第一次复制的就是基地址为401000的程序代码段
但是3.61版后这个方法不行了,因为子进程的程序代码经过了xor后的代码,这个xor解码由父进程完成。但是对数据段
没有加密。所以可以在这里得到。

在00DD38D7  PUSH EAX 下断,跟踪直到基地址是00595000就可以在经过msvcrt.memcpy这个函数
后把这个段的代码用OD的二进制复制方法复制下来,然后再用OD打开LordPE原来dump的程序。把数据粘连到00595000段,这
就是个原始的data段了。


2.IAT表的处理

 再向下运行,经过2个解码段

00DD4253   >ADD EAX,4
00DD4256   >MOV DWORD PTR SS:[EBP-1B44],EAX
00DD425C  ^>JMP SHORT 00DD4228 
00DD425E   >XCHG EDX,EDI         //解码完成的特征代码
00DD4260   >NOP
00DD4261   >XCHG EDX,EDI
00DD4263   >JPE SHORT 00DD4263


经过上面的解码后向下查找第三个anti的地方:

00DD452E   >JNZ SHORT 00DD4541
00DD4530   >MOV EAX,DWORD PTR SS:[EBP-1D74]
00DD4536   >MOV EAX,DWORD PTR DS:[EAX+4]
00DD4539   >MOV DWORD PTR SS:[EBP-1B4C],EAX
00DD453F   >JMP SHORT 00DD4546                //**********
00DD4541  ^>JMP 00DD4496                      //*********            
00DD4546   >AND BYTE PTR SS:[EBP-1B54],0      //第三个anti的特征代码
00DD454D   >CMP DWORD PTR SS:[EBP-1910],0
00DD4554   >JNZ SHORT 00DD4595
00DD4556   >MOV EAX,DWORD PTR DS:[DE9560]
00DD455B   >MOV AL,BYTE PTR DS:[EAX+3D2F]
00DD4561   >MOV BYTE PTR SS:[EBP-31B8],AL
00DD4567   >MOVZX EAX,BYTE PTR SS:[EBP-31B8]      <--第三个anti,修改下面的EAX值为0
00DD456E   >TEST EAX,EAX
00DD4570   >JE SHORT 00DD4595


过了第三个anti后就来到IAT解码的地方:


00DD467A  CALL DWORD PTR DS:[DDB138]               ; kernel32.VirtualProtect
00DD4680  PUSH 1
00DD4682  POP EAX
00DD4683  TEST EAX,EAX
00DD4685  JE 00DD494A
00DD468B  AND WORD PTR SS:[EBP-1D7C],0
00DD4693  AND DWORD PTR SS:[EBP-1D84],0
00DD469A  AND DWORD PTR SS:[EBP-1D80],0
00DD46A1  MOV EAX,DWORD PTR SS:[EBP-1780]
00DD46A7  MOVSX EAX,BYTE PTR DS:[EAX]
00DD46AA  TEST EAX,EAX
00DD46AC  JNZ SHORT 00DD46F2
00DD46AE  LEA ECX,DWORD PTR SS:[EBP-17C0]
00DD46B4  CALL 00DB1040
00DD46B9  MOVZX EAX,AL
00DD46BC  CDQ
00DD46BD  PUSH 14
00DD46BF  POP ECX
00DD46C0  IDIV ECX
00DD46C2  MOV EAX,DWORD PTR SS:[EBP-17E4]
00DD46C8  MOV ECX,DWORD PTR SS:[EBP+EDX*4-1960]     ; 修改为 XOR  ECX,ECX
00DD46CF  MOV DWORD PTR DS:[EAX],ECX
00DD46D1  MOV EAX,DWORD PTR SS:[EBP-17E4]
00DD46D7  ADD EAX,4
00DD46DA  MOV DWORD PTR SS:[EBP-17E4],EAX
00DD46E0  MOV EAX,DWORD PTR SS:[EBP-1780]
00DD46E6  INC EAX
00DD46E7  MOV DWORD PTR SS:[EBP-1780],EAX
00DD46ED  JMP 00DD494A
00DD46F2  MOV EAX,DWORD PTR SS:[EBP-1780]
00DD46F8  MOVZX EAX,BYTE PTR DS:[EAX]
00DD46FB  CMP EAX,0FF
00DD4700  JNZ 00DD4790
00DD4706  MOV EAX,DWORD PTR SS:[EBP-1780]
00DD470C  INC EAX
00DD470D  MOV DWORD PTR SS:[EBP-1780],EAX
00DD4713  MOV EAX,DWORD PTR SS:[EBP-1780]
00DD4719  MOV AX,WORD PTR DS:[EAX]
00DD471C  MOV WORD PTR SS:[EBP-1D7C],AX
00DD4723  MOV EAX,DWORD PTR SS:[EBP-1780]
00DD4729  INC EAX
00DD472A  INC EAX
00DD472B  MOV DWORD PTR SS:[EBP-1780],EAX
00DD4731  CMP DWORD PTR SS:[EBP-1B4C],0
00DD4738  JE SHORT 00DD478B
00DD473A  MOV EAX,DWORD PTR SS:[EBP-1B4C]
00DD4740  MOV DWORD PTR SS:[EBP-1D88],EAX
00DD4746  JMP SHORT 00DD4757
00DD4748  MOV EAX,DWORD PTR SS:[EBP-1D88]
00DD474E  ADD EAX,0C
00DD4751  MOV DWORD PTR SS:[EBP-1D88],EAX
00DD4757  MOV EAX,DWORD PTR SS:[EBP-1D88]
00DD475D  CMP DWORD PTR DS:[EAX+8],0
00DD4761  JE SHORT 00DD478B
00DD4763  MOVZX EAX,WORD PTR SS:[EBP-1D7C]
00DD476A  MOV ECX,DWORD PTR SS:[EBP-1D88]
00DD4770  MOVZX ECX,WORD PTR DS:[ECX+4]
00DD4774  CMP EAX,ECX
00DD4776  JNZ SHORT 00DD4789
00DD4778  MOV EAX,DWORD PTR SS:[EBP-1D88]
00DD477E  MOV EAX,DWORD PTR DS:[EAX+8]
00DD4781  MOV DWORD PTR SS:[EBP-1D80],EAX
00DD4787  JMP SHORT 00DD478B
00DD4789  JMP SHORT 00DD4748
00DD478B  JMP 00DD482D
00DD4790  MOV EAX,DWORD PTR SS:[EBP-1780]
00DD4796  MOV DWORD PTR SS:[EBP-1D84],EAX
00DD479C  PUSH 0
00DD479E  PUSH DWORD PTR SS:[EBP-1780]
00DD47A4  CALL DWORD PTR DS:[DDB2C4]               ; msvcrt.strchr
00DD47AA  POP ECX
00DD47AB  POP ECX
00DD47AC  INC EAX
00DD47AD  MOV DWORD PTR SS:[EBP-1780],EAX
00DD47B3  CMP DWORD PTR SS:[EBP-1B4C],0
00DD47BA  JE SHORT 00DD482D
00DD47BC  MOV EAX,DWORD PTR SS:[EBP-1B4C]
00DD47C2  MOV DWORD PTR SS:[EBP-1D8C],EAX
00DD47C8  JMP SHORT 00DD47D9
00DD47CA  MOV EAX,DWORD PTR SS:[EBP-1D8C]
00DD47D0  ADD EAX,0C
00DD47D3  MOV DWORD PTR SS:[EBP-1D8C],EAX
00DD47D9  MOV EAX,DWORD PTR SS:[EBP-1D8C]
00DD47DF  CMP DWORD PTR DS:[EAX+8],0
00DD47E3  JE SHORT 00DD482D
00DD47E5  PUSH 100
00DD47EA  LEA EAX,DWORD PTR SS:[EBP-1E8C]
00DD47F0  PUSH EAX
00DD47F1  MOV EAX,DWORD PTR SS:[EBP-1D8C]
00DD47F7  PUSH DWORD PTR DS:[EAX]
00DD47F9  CALL 00DB7CF7
00DD47FE  ADD ESP,0C
00DD4801  LEA EAX,DWORD PTR SS:[EBP-1E8C]
00DD4807  PUSH EAX
00DD4808  PUSH DWORD PTR SS:[EBP-1D84]
00DD480E  CALL DWORD PTR DS:[DDB330]               ; msvcrt._stricmp
00DD4814  POP ECX
00DD4815  POP ECX
00DD4816  TEST EAX,EAX
00DD4818  JNZ SHORT 00DD482B
00DD481A  MOV EAX,DWORD PTR SS:[EBP-1D8C]
00DD4820  MOV EAX,DWORD PTR DS:[EAX+8]
00DD4823  MOV DWORD PTR SS:[EBP-1D80],EAX
00DD4829  JMP SHORT 00DD482D
00DD482B  JMP SHORT 00DD47CA
00DD482D  CMP DWORD PTR SS:[EBP-1D80],0
00DD4834  JNZ SHORT 00DD4875                       // 这里NOP掉
00DD4836  MOVZX EAX,WORD PTR SS:[EBP-1D7C]
00DD483D  TEST EAX,EAX
00DD483F  JE SHORT 00DD4850
00DD4841  MOVZX EAX,WORD PTR SS:[EBP-1D7C]
00DD4848  MOV DWORD PTR SS:[EBP-323C],EAX
00DD484E  JMP SHORT 00DD485C
00DD4850  MOV EAX,DWORD PTR SS:[EBP-1D84]
00DD4856  MOV DWORD PTR SS:[EBP-323C],EAX
00DD485C  PUSH DWORD PTR SS:[EBP-323C]
00DD4862  PUSH DWORD PTR SS:[EBP-1B48]
00DD4868  CALL 00DB9C5C                          //这里修改为 call GetProcAddress 
00DD486D  POP ECX                                 // 这里NOP掉
00DD486E  POP ECX                                 // 这里NOP掉
00DD486F  MOV DWORD PTR SS:[EBP-1D80],EAX
00DD4875  CMP DWORD PTR SS:[EBP-1D80],0
00DD487C  JNZ 00DD491A
00DD4882  MOVZX EAX,WORD PTR SS:[EBP-1D7C]
00DD4889  TEST EAX,EAX
00DD488B  JE SHORT 00DD48E1
00DD488D  CALL DWORD PTR DS:[DDB0D8]               ; ntdll.RtlGetLastWin32Error
00DD4893  CMP EAX,32
00DD4896  JNZ SHORT 00DD48A4
00DD4898  MOV DWORD PTR SS:[EBP-1D80],0DB9C51
00DD48A2  JMP SHORT 00DD48DF
00DD48A4  MOV EAX,DWORD PTR SS:[EBP+8]
00DD48A7  MOV EAX,DWORD PTR DS:[EAX]
00DD48A9  MOV DWORD PTR DS:[EAX],3
00DD48AF  CALL DWORD PTR DS:[DDB0D8]               ; ntdll.RtlGetLastWin32Error
00DD48B5  PUSH EAX
00DD48B6  MOVZX EAX,WORD PTR SS:[EBP-1D7C]
00DD48BD  PUSH EAX
00DD48BE  PUSH DWORD PTR SS:[EBP-1C64]
00DD48C4  PUSH 0DE19D4                             ; ASCII "File "%s", ordinal %d (error %d)"
00DD48C9  MOV EAX,DWORD PTR SS:[EBP+8]
00DD48CC  PUSH DWORD PTR DS:[EAX+4]
00DD48CF  CALL DWORD PTR DS:[DDB2C0]               ; msvcrt.sprintf
00DD48D5  ADD ESP,14
00DD48D8  XOR EAX,EAX
00DD48DA  JMP 00DD58C2
00DD48DF  JMP SHORT 00DD491A
00DD48E1  MOV EAX,DWORD PTR SS:[EBP+8]
00DD48E4  MOV EAX,DWORD PTR DS:[EAX]
00DD48E6  MOV DWORD PTR DS:[EAX],3
00DD48EC  CALL DWORD PTR DS:[DDB0D8]               ; ntdll.RtlGetLastWin32Error
00DD48F2  PUSH EAX
00DD48F3  PUSH DWORD PTR SS:[EBP-1D84]
00DD48F9  PUSH DWORD PTR SS:[EBP-1C64]
00DD48FF  PUSH 0DE19B0                             ; ASCII "File "%s", function "%s" (error %d)"
00DD4904  MOV EAX,DWORD PTR SS:[EBP+8]
00DD4907  PUSH DWORD PTR DS:[EAX+4]
00DD490A  CALL DWORD PTR DS:[DDB2C0]               ; msvcrt.sprintf
00DD4910  ADD ESP,14
00DD4913  XOR EAX,EAX
00DD4915  JMP 00DD58C2
00DD491A  MOV EAX,DWORD PTR SS:[EBP-17E4]
00DD4920  CMP EAX,DWORD PTR SS:[EBP-1798]
00DD4926  JNB SHORT 00DD4945
00DD4928  MOV EAX,DWORD PTR SS:[EBP-17E4]
00DD492E  MOV ECX,DWORD PTR SS:[EBP-1D80]
00DD4934  MOV DWORD PTR DS:[EAX],ECX               // 在此处设一次断以找到 iat的位置
00DD4936  MOV EAX,DWORD PTR SS:[EBP-17E4]
00DD493C  ADD EAX,4
00DD493F  MOV DWORD PTR SS:[EBP-17E4],EAX
00DD4945  JMP 00DD4680


以上是采用了jingulong的方法,十分的好用。

由于没有采用远地址IAT调用,所以到这里得到了完整的IAT表,用Import.Reconstructor得到完整的表。修复dump的程序就可以
正常运行了。

3.CC的修复

  CC的修复比较麻烦,因为arm壳运行时并不需要具体的跳转类型,他只要确定是跳或者不跳 跳转的地址就能运行了。所以类型
不是十分的清晰。

 再次用OD加载原主程序,he WaitForDebugEvent F9运行程序中断后取消这个断点,bp GetThreadContext F9运行中断后再运行一次
再次中断后Alt+F9返回到壳的子进程中,F8运行程序到这里:

006011F1  CALL Uedit320.005E9F90
006011F6  ADD ESP,0C
006011F9  MOV DWORD PTR SS:[EBP-1194],EAX
006011FF  MOV EAX,DWORD PTR SS:[EBP-1194]
00601205  XOR EDX,EDX
00601207  MOV ECX,10
0060120C  DIV ECX
0060120E  MOV DWORD PTR SS:[EBP-1198],EDX
00601214  MOV EDX,DWORD PTR SS:[EBP-13AC]          ; Uedit320.0040CD96
0060121A  PUSH EDX                                 //这里是程序的CC地址下面的首地址
0060121B  MOV EAX,DWORD PTR SS:[EBP-1198]          //跟踪这里就可以得到所有CC的地址了
00601221  CALL DWORD PTR DS:[EAX*4+62A838]
00601228  ADD ESP,4
0060122B  MOV DWORD PTR SS:[EBP-1468],EAX
00601231  MOV DWORD PTR SS:[EBP-146C],0
0060123B  MOV ECX,DWORD PTR SS:[EBP-1198]
00601241  MOV EDX,DWORD PTR DS:[ECX*4+62C6D4]
00601248  MOV DWORD PTR SS:[EBP-118C],EDX
0060124E  MOV EAX,DWORD PTR SS:[EBP-146C]
00601254  CMP EAX,DWORD PTR SS:[EBP-118C]
0060125A  JGE SHORT Uedit320.006012B8
0060125C  MOV EAX,DWORD PTR SS:[EBP-118C]
00601262  SUB EAX,DWORD PTR SS:[EBP-146C]
00601268  CDQ
00601269  SUB EAX,EDX
0060126B  SAR EAX,1
0060126D  MOV ECX,DWORD PTR SS:[EBP-146C]
00601273  ADD ECX,EAX
00601275  MOV DWORD PTR SS:[EBP-1470],ECX
0060127B  MOV EDX,DWORD PTR SS:[EBP-1198]
00601281  MOV EAX,DWORD PTR DS:[EDX*4+62C68C]
00601288  MOV ECX,DWORD PTR SS:[EBP-1470]
0060128E  MOV EDX,DWORD PTR SS:[EBP-1468]
00601294  CMP EDX,DWORD PTR DS:[EAX+ECX*4]
00601297  JBE SHORT Uedit320.006012AA
00601299  MOV EAX,DWORD PTR SS:[EBP-1470]
0060129F  ADD EAX,1
006012A2  MOV DWORD PTR SS:[EBP-146C],EAX
006012A8  JMP SHORT Uedit320.006012B6
006012AA  MOV ECX,DWORD PTR SS:[EBP-1470]
006012B0  MOV DWORD PTR SS:[EBP-118C],ECX
006012B6  JMP SHORT Uedit320.0060124E        //这个循环是对地址的计算,用于下面的判断
006012B8  PUSHAD
006012B9  XOR EAX,EAX
006012BB  JNZ SHORT Uedit320.006012BF
006012BD  JMP SHORT Uedit320.006012D4


继续向前:

00601357   >MOV EAX,DWORD PTR SS:[EBP-1198]
0060135D   >MOV ECX,DWORD PTR DS:[EAX*4+62C714]
00601364   >MOV EDX,DWORD PTR SS:[EBP-146C]
0060136A   >XOR EAX,EAX
0060136C   >MOV AL,BYTE PTR DS:[ECX+EDX]
0060136F   >MOV DWORD PTR SS:[EBP-1488],EAX
00601375   >MOV EAX,DWORD PTR SS:[EBP-1488]
0060137B   >CDQ
0060137C   >AND EDX,0F
0060137F   >ADD EAX,EDX
00601381   >SAR EAX,4
00601384   >MOV DWORD PTR SS:[EBP-1480],EAX
0060138A   >MOV ECX,DWORD PTR SS:[EBP-1488]
00601390   >AND ECX,8000000F
00601396   >JNS SHORT Uedit320.0060139D
00601398   >DEC ECX
00601399   >OR ECX,FFFFFFF0
0060139C   >INC ECX
0060139D   >MOV DWORD PTR SS:[EBP-1484],ECX
006013A3   >MOV EDX,DWORD PTR SS:[EBP-1480]
006013A9   >CMP EDX,DWORD PTR SS:[EBP-1484]
006013AF   >JNZ SHORT Uedit320.006013CC
006013B1   >MOV EAX,DWORD PTR SS:[EBP-1484]
006013B7   >ADD EAX,1
006013BA   >AND EAX,8000000F
006013BF   >JNS SHORT Uedit320.006013C6
006013C1   >DEC EAX
006013C2   >OR EAX,FFFFFFF0
006013C5   >INC EAX
006013C6   >MOV DWORD PTR SS:[EBP-1484],EAX
006013CC   >MOV ECX,DWORD PTR SS:[EBP-1488]
006013D2   >MOV EDX,DWORD PTR SS:[EBP-1480]
006013D8   >MOV EAX,DWORD PTR DS:[ECX*4+62BED0]
006013DF   >XOR EAX,DWORD PTR DS:[EDX*4+62625C]
006013E6   >MOV ECX,DWORD PTR SS:[EBP-1484]
006013EC   >XOR EAX,DWORD PTR DS:[ECX*4+62625C]
006013F3   >MOV DWORD PTR SS:[EBP-1478],EAX
006013F9   >MOV EDX,DWORD PTR SS:[EBP-13A4]
006013FF   >AND EDX,0FD7
00601405   >PUSH EDX
00601406   >MOV EAX,DWORD PTR SS:[EBP-1488]
0060140C   >MOVSX ECX,BYTE PTR DS:[EAX+62A730]   //取第一个标志
00601413   >CALL DWORD PTR DS:[ECX*4+62A838]     //根据标志计算
0060141A   >ADD ESP,4
0060141D   >MOV DWORD PTR SS:[EBP-1474],EAX
00601423   >MOV EDX,DWORD PTR SS:[EBP-13B8]
00601429   >PUSH EDX
0060142A   >MOV EAX,DWORD PTR SS:[EBP-1474]
00601430   >PUSH EAX
00601431   >CALL DWORD PTR SS:[EBP-1478]
00601437   >ADD ESP,8
0060143A   >PUSH EAX
0060143B   >MOV ECX,DWORD PTR SS:[EBP-1488]
00601441   >MOVSX EDX,BYTE PTR DS:[ECX+62A730]   //取第二个标志
00601448   >CALL DWORD PTR DS:[EDX*4+62A878]     //根据标志计算
0060144F   >ADD ESP,4
00601452   >MOV DWORD PTR SS:[EBP-147C],EAX      //返回值用于跳与不跳的判断
00601458   >MOV EAX,DWORD PTR SS:[EBP-147C]
0060145E   >AND EAX,1
00601461   >TEST EAX,EAX                          //判断上面计算的值,如果EAX=0
00601463   >JE Uedit320.00601517                  //就不跳,否则就是跳转。
00601469   >PUSHAD
0060146A   >XOR EAX,EAX
0060146C   >JNZ SHORT Uedit320.00601470
0060146E   >JMP SHORT Uedit320.00601485

如果上面的EAX值不是0 即必须跳转就来到下面计算跳转偏移的地方:

0060148E   >POPAD
0060148F   >MOV ECX,DWORD PTR SS:[EBP-1198]
00601495   >MOV ECX,DWORD PTR DS:[ECX*4+62C64C]
0060149C   >MOV EAX,DWORD PTR SS:[EBP-146C]
006014A2   >XOR EDX,EDX
006014A4   >MOV ESI,10
006014A9   >DIV ESI
006014AB   >MOV EAX,DWORD PTR SS:[EBP-146C]
006014B1   >MOV ECX,DWORD PTR DS:[ECX+EAX*4]       //表1中的值
006014B4   >XOR ECX,DWORD PTR SS:[EBP+EDX*4-1170]  //xor 表2中的值,得到的ECX就是偏移
006014BB   >MOV EDX,DWORD PTR SS:[EBP-13AC]        //CC地址下面的首地址
006014C1   >ADD EDX,ECX                            //相加就是要到达的地址
006014C3   >MOV DWORD PTR SS:[EBP-13AC],EDX        //这个值就是子进程EIP的值


如果上面判断的值EAX=0 即不跳就来到这里:

00601522  MOV EAX,DWORD PTR SS:[EBP-1198]          
00601528  MOV ECX,DWORD PTR DS:[EAX*4+62C758]      //跳转代码长度-1表
0060152F  MOV EDX,DWORD PTR SS:[EBP-146C]          //取值的偏移
00601535  XOR EAX,EAX
00601537  MOV AL,BYTE PTR DS:[ECX+EDX]             //根据上面的偏移取出跳转代码长度-1的值
0060153A  MOV ECX,DWORD PTR SS:[EBP-13AC]          //CC地址下面的首地址
00601540  ADD ECX,EAX                              //相加就是要到达的地址
00601542  MOV DWORD PTR SS:[EBP-13AC],ECX          //这个值就是子进程EIP的值



跳转代码长度-1表:

00DB8070  01 04 01 05 01 04 01 01  
00DB8078  01 04 01 05 01 01 05 01  
00DB8080  01 05 05 04 05 01 01 05  
00DB8088  01 01 01 01 01 05 01 01  
00DB8090  05 01 01 01 01 05 01 01  
00DB8098  01 01 01 01 04 05 01 01  
00DB80A0  01 05 05 01 05 05 04 05  
00DB80A8  01 05 01 01 01 05 01 01  
00DB80B0  05 01 04 01 05 01 01 05  
00DB80B8  05 01 01 04 05 01 01 04  
00DB80C0  05 01 01 01 01 01 05 05  
00DB80C8  01 01 01 01 04 01 05 01  
00DB80D0  05 05 01 01 05 05 01 01  
00DB80D8  01 05 01 05 01 01 01 01  
00DB80E0  01 01 01 04 01 05 01 05  
00DB80E8  01 05 01 05 05 04 01 05  
00DB80F0  04 04 01 01 01 01 01 01  
00DB80F8  01 05 01 01 05 05 01 04  
00DB8100  05 01 04 05 01 05 05 04  
00DB8108  01 01 05 01 01 01 01 01  
00DB8110  01 01 01 01 01 05 01 05  
00DB8118  04 05 01 01 01 01 05 01  
00DB8120  05 05 05 01 01 05 05 05  
00DB8128  05 01 01 05 01 01 05     


跟踪上面的关键地方就能得到一个cc跳转表。根据这个表修改dump的程序。
当然你也可以修改子进程的跳转方向,即修改:
0060145E   >AND EAX,1
00601461   >TEST EAX,EAX                          //判断上面计算的值,如果EAX=0
00601463   >JE Uedit320.00601517                  //就不跳,否则就是跳转。

修改EAX的值就可以让程序按自己的需要跳转了:)


关于这篇脱文,这只是我个人的跟踪所得,未必正确。请不必当成教条!
我的知识也是来源于网上,所得也不敢独享,所以有文章。



 
                                      fxyang

                                     2004.4.28