(二)cc修复
下面我尝试着来修复CC。cc实际上就是int3指令,armadillo把程序中的一些跳转指令改成int3。子进程运行到int3时发生异常,父进程可以捕捉到,然后计算出子进程该不该跳转,如果跳转,跳转量是多少,如果不跳转,下一条指令应从哪里开始。通过getthreadcontext和setthreadcontext函数来干预子进程的运行。因此程序脱壳后,里面的int3指令不修复成原本的跳转指令,程序是不可能运行起来的。
但问题是:脱壳程序中哪些cc是int3指令,哪些cc是数据呢?原先版本的armardillo可以完全区分开来,但现在的版本好像不能够区分,至少我没有找到方法,不知高手们是采用什么办法的。从技术角度来讲,armadillo可以不用区分。我们试想一下:armardillo可以把原程序中所有跳转指令都改成int3,然后连同程序中的cc数据一起进行计算得到一张总表。在加壳时却只随机选一些跳转指令改成int3,但使用的还是那张总表。程序完全可以运行。但我们怎么才能知道总表中哪些是跳转指令呢?我觉得不能,因此也就很难完美修复。
我想到修复的方法有两种,一是在OD中运行加壳程序,设置条件记录断点,然后把程序所有的功能都运行一遍,得到子进程发生int3的地址。二是设计一代码分析器,分析脱壳程序中哪些是int3指令,哪些不是。这两种方法都不能算是完美修复。我的方法是借用OD来找到int3。
我们的目标是得到四个表:int3地址表、跳转类型表、跳转量表及跳转指令长度表。有了这四个表,我们就可以修复cc了。
我们先看第一张int3地址表。在od中打开脱壳程序,从401000~98cfff都是程序的内容,包括代码和资源。armadillo把它们放在同一节中。查找二进制55 8b ec(PUSH EBP MOV EBP, ESP)找到代码开始的部分在5fe660。把5fe660~98cfff选上然后复制到文件中,用ultraedit打开文件,选上“列出包含字符串的行”,查找文本int3。ok,找到如下形式的int3:
0060063E CC INT3 0060063F CC INT3 0060D481 CC INT3 0060D482 CC INT3 0060D483 CC INT3 .....
使用ultraedit的列编辑功能编辑成:
3E 06 60 00 3F 06 60 00 81 D4 60 00 82 D4 60 00 83 D4 60 00 84 D4 60 00 .....
当然这里面有很多都是不符合条件的,是int3原始表。先保存好,下面要用。
在OD中重新打开BMP.exe。下he GetThreadContext,运行,第二次停住时,看堆栈窗:
0012DA78 009EBC88 /CALL to GetThreadContext from BMP.009EBC82 0012DA7C 00000050 |hThread = 00000050 (window) 0012DA80 0012E10C \pContext = 0012E10C
在follow in dump 来到0012E10C。按alt+f9回到用户空间。
0012E1AC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0012E1BC 00 00 00 00 64 EE 12 00 DC 37 79 00 1B 00 00 00 ....d?.?y.... 0012E1CC 46 02 00 00 24 EE 12 00 23 00 00 00 00 00 00 00 F..$?.#.......
12e1c4处的7937dc就是子进程发生的第一个int3地址+1,我们可以用OD把脱壳程序打开看看,运行出的第一个错也是那。 0012E1CC处的246是子进程的Flag寄存器内容。
009EBC82 CALL DWORD PTR DS:[<&KERNEL32.GetThreadC>; 009EBC88 PUSH EAX //停在这,这条指令到009EBCCA都是垃圾指令 009EBC89 NOT EAX 009EBC8B BSWAP EAX 009EBC8D POP EAX 009EBC8E JNB SHORT BMP.009EBC90 009EBC90 PUSHFD 009EBC91 PUSHAD
009EBCC1 MOV EAX, C80F9D61 009EBCC6 NOT ECX 009EBCC8 BSWAP EAX 009EBCCA NOT ECX 009EBCCC MOV DWORD PTR SS:[EBP-1468], 0 009EBCD6 PUSH -1 009EBCD8 PUSH 4 009EBCDA LEA EDX, DWORD PTR SS:[EBP-13AC] ; [12e1c4]=7937dc,子进程发生int3的地址+1 009EBCE0 PUSH EDX 009EBCE1 CALL BMP.009D4F90 ; 对int3地址运算 009EBCE6 ADD ESP, 0C 009EBCE9 MOV DWORD PTR SS:[EBP-1194], EAX ; 运算结果 009EBCEF MOV EAX, DWORD PTR SS:[EBP-1194] 009EBCF5 XOR EDX, EDX 009EBCF7 MOV ECX, 10 009EBCFC DIV ECX ; 运算结果除以10 009EBCFE MOV DWORD PTR SS:[EBP-1198], EDX ; 取余数 009EBD04 MOV EDX, DWORD PTR SS:[EBP-13AC] ; int3地址+1 009EBD0A PUSH EDX 009EBD0B MOV EAX, DWORD PTR SS:[EBP-1198] ; 前面得到的余数 009EBD11 CALL DWORD PTR DS:[EAX*4+A15838] ; 再次运算。 009EBD18 ADD ESP, 4 009EBD1B MOV DWORD PTR SS:[EBP-1468], EAX ; 运算结果,将用于在table1(int3地址计算结果表)中查找 009EBD21 >MOV DWORD PTR SS:[EBP-146C], 0 009EBD2B MOV ECX, DWORD PTR SS:[EBP-1198] 009EBD31 MOV EDX, DWORD PTR DS:[ECX*4+A176D4] 009EBD38 MOV DWORD PTR SS:[EBP-118C], EDX 009EBD3E MOV EAX, DWORD PTR SS:[EBP-146C] 009EBD44 CMP EAX, DWORD PTR SS:[EBP-118C] 009EBD4A JGE SHORT BMP.009EBDA8 009EBD4C MOV EAX, DWORD PTR SS:[EBP-118C] 009EBD52 SUB EAX, DWORD PTR SS:[EBP-146C] 009EBD58 CDQ 009EBD59 SUB EAX, EDX 009EBD5B SAR EAX, 1 009EBD5D MOV ECX, DWORD PTR SS:[EBP-146C] 009EBD63 ADD ECX, EAX 009EBD65 MOV DWORD PTR SS:[EBP-1470], ECX 009EBD6B MOV EDX, DWORD PTR SS:[EBP-1198] ; 前面得到的余数 009EBD71 MOV EAX, DWORD PTR DS:[EDX*4+A1768C] ; [A1768C]开始的是table1地址表,根据前面得到的余数找到table1的地址 009EBD78 MOV ECX, DWORD PTR SS:[EBP-1470] 009EBD7E MOV EDX, DWORD PTR SS:[EBP-1468] 009EBD84 CMP EDX, DWORD PTR DS:[EAX+ECX*4] 009EBD87 JBE SHORT BMP.009EBD9A 009EBD89 MOV EAX, DWORD PTR SS:[EBP-1470] 009EBD8F ADD EAX, 1 009EBD92 MOV DWORD PTR SS:[EBP-146C], EAX 009EBD98 JMP SHORT BMP.009EBDA6 009EBD9A MOV ECX, DWORD PTR SS:[EBP-1470] 009EBDA0 MOV DWORD PTR SS:[EBP-118C], ECX 009EBDA6 JMP SHORT BMP.009EBD3E 009EBDA8 PUSHAD ; eax=查表结果(前面运算结果在table1中的序号) 009EBDA9 NOP ....... //nop掉垃圾指令 009EBDCB NOP 009EBDCC NOP 009EBDCD POPAD 009EBDCE MOV EDX, DWORD PTR SS:[EBP-1198] 前面的余数 009EBDD4 MOV EAX, DWORD PTR DS:[EDX*4+A1768C] ; table1地址 009EBDDB MOV ECX, DWORD PTR SS:[EBP-146C] 009EBDE1 MOV EDX, DWORD PTR DS:[EAX+ECX*4] 009EBDE4 CMP EDX, DWORD PTR SS:[EBP-1468] ; 再比较一下,看是否相等 009EBDEA JNZ BMP.009EC102 ........ // 垃圾指令
009EBE47 MOV EAX, DWORD PTR SS:[EBP-1198] 前面的余数 009EBE4D MOV ECX, DWORD PTR DS:[EAX*4+A17714] ; table2(跳转类型代号表) 009EBE54 MOV EDX, DWORD PTR SS:[EBP-146C] 009EBE5A XOR EAX, EAX 009EBE5C MOV AL, BYTE PTR DS:[ECX+EDX] ; 得到跳转类型代号 009EBE5F MOV DWORD PTR SS:[EBP-1488], EAX 009EBE65 MOV EAX, DWORD PTR SS:[EBP-1488] 009EBE6B CDQ 009EBE6C AND EDX, 0F 009EBE6F ADD EAX, EDX 009EBE71 SAR EAX, 4 009EBE74 MOV DWORD PTR SS:[EBP-1480], EAX 009EBE7A MOV ECX, DWORD PTR SS:[EBP-1488] 009EBE80 AND ECX, 8000000F 009EBE86 JNS SHORT BMP.009EBE8D 009EBE88 DEC ECX 009EBE89 OR ECX, FFFFFFF0 009EBE8C INC ECX 009EBE8D MOV DWORD PTR SS:[EBP-1484], ECX 009EBE93 MOV EDX, DWORD PTR SS:[EBP-1480] 009EBE99 CMP EDX, DWORD PTR SS:[EBP-1484] 009EBE9F JNZ SHORT BMP.009EBEBC 009EBEA1 MOV EAX, DWORD PTR SS:[EBP-1484] 009EBEA7 ADD EAX, 1 009EBEAA AND EAX, 8000000F 009EBEAF JNS SHORT BMP.009EBEB6 009EBEB1 DEC EAX 009EBEB2 OR EAX, FFFFFFF0 009EBEB5 INC EAX 009EBEB6 MOV DWORD PTR SS:[EBP-1484], EAX 009EBEBC MOV ECX, DWORD PTR SS:[EBP-1488] 009EBEC2 MOV EDX, DWORD PTR SS:[EBP-1480] 009EBEC8 MOV EAX, DWORD PTR DS:[ECX*4+A16ED0] 009EBECF XOR EAX, DWORD PTR DS:[EDX*4+A1125C] 009EBED6 MOV ECX, DWORD PTR SS:[EBP-1484] 009EBEDC XOR EAX, DWORD PTR DS:[ECX*4+A1125C] 009EBEE3 MOV DWORD PTR SS:[EBP-1478], EAX 009EBEE9 MOV EDX, DWORD PTR SS:[EBP-13A4] ; 子进程context的flag寄存器内容 009EBEEF AND EDX, 0FD7
1 2 3 4 5 下一页 |