这壳好像是一猛壳!
这个壳成功的运用了花指令生成引擎,小弟最终还是没能分析出OEP出来,我就给大家看下学习记录算了。
我分析到得保护技术:花指令,内存访问异常,花指令用的好成熟,好像还有调用堆栈执行代码异常终止。
花指令在于实践,所以大家一定要拿着OD弄一下,
程序以一个CALL 004050AA开始,然后就进行自定位,
代码:
004050AA 5D POP EBP CALL会压入下条指令的地址保存,以便返回 004050AB 81ED 05000000 SUB EBP,5 定位到程序代码的开始处,以便控制外壳段 接下来就是加载外壳段储存的Kernel32.dll,然后装载,获得VirtualAlloc的地址,再调用VirtualAlloc分配指定大小的内存,用来接收解码后的外壳段代码 004050B1 8D75 3D LEA ESI,DWORD PTR SS:[EBP+3D] ; "Kernel32.dll" 004050B4 56 PUSH ESI ; Kernel32.dll的偏移地址 004050B5 FF55 31 CALL DWORD PTR SS:[EBP+31] ; GetModuleHandleA,获得模块基址 004050B8 8DB5 81000000 LEA ESI,DWORD PTR SS:[EBP+81] ; “VirtualAlloc” 004050BE 56 PUSH ESI ; VirtualAlloc的偏移地址 004050BF 50 PUSH EAX ; Kernel32.dll的模块基址 004050C0 FF55 2D CALL DWORD PTR SS:[EBP+2D] ; GetProcAddress获得函数地址 004050C3 8985 8E000000 MOV DWORD PTR SS:[EBP+8E],EAX ; VirtualAlloc函数地址保存的地方 004050C9 6A 04 PUSH 4 ; 保护方式PAGE_READWRITE 004050CB 68 00100000 PUSH 1000 ; 分配的类型MEM_COMMIT 004050D0 68 28900000 PUSH 9028 ; 分配的大小 004050D5 6A 00 PUSH 0 ; 分配大小的起始位置,用来计算 004050D7 FF95 8E000000 CALL DWORD PTR SS:[EBP+8E] ; CALL VirtualAlloc 分配好虚拟内存后,然后解密外壳段代码拷贝到分配的内存里面,这个过程中随机生成花指令,然后在JMP跳到分配的内存里面去,执行代码 004050DD 50 PUSH EAX ; 虚拟内存的地址 004050DE 8B9D 7D000000 MOV EBX,DWORD PTR SS:[EBP+7D] ; 要解码的偏移,19C 004050E4 03DD ADD EBX,EBP ; 加上程序开始的地址00405000就是0040519C这个地方了 004050E6 50 PUSH EAX ; 分配内存的虚拟地址,参数2 004050E7 53 PUSH EBX ; 原来的位置,参数一 004050E8 E8 04000000 CALL PECompac.004050F1 ; CALL 解码拷贝 004050ED 5A POP EDX ; 恢复虚拟地址的地址,也就是MOV前面那个push eax 004050EE 55 PUSH EBP ; 外壳代码基址 004050EF FFE2 JMP EDX ; JMP虚拟内存 现在开始解密后的内容,这段代码好多花指令,大家要注意: 003D0000 /EB 01 JMP SHORT 003D0003 ; 跳到3D0003 003D0002 |90 NOP ; 这里的OF生成的花指令,原指令是RDTSC,我们右键二进制编辑把0x0F NOP掉,保留0x31操作码 003D0003 31F0 XOR EAX,ESI ; 分配内存大小和储存字符串VirtualAlloc的地址异或 003D0005 EB 0C JMP SHORT 003D0013 ;跳到下面PUSH ECX那里 003D0007 33C8 XOR ECX,EAX ;ECX和EAX异或 003D0009 EB 03 JMP SHORT 003D000E ;跳到花指令,我现在把花指令操作码0x0F NOP掉了, 003D000B EB 09 JMP SHORT 003D0016 跳到下面XOR EAX,ESI那里,那里原来也是花指令 003D000D 90 NOP 原来的指令是,003D000D 0F 59 74 05 MULPS XMM6,DQWORD PTR SS:[EBP+EAX+75],把操作码0x0F改为90 003D000E 59 POP ECX 恢复ECX的值 003D000F 74 05 JE SHORT 003D0016 ZF等于1就跳 003D0011 ^ 75 F8 JNZ SHORT 003D000B ZF等于0就向上跳 003D0013 51 PUSH ECX 003D0014 ^ EB F1 JMP SHORT 003D0007 ;跳到XOR ECX,EAX那里 003D0016 EB 01 JMP SHORT 003D0019 003D0018 90 NOP 同上,0x0F改为90 003D0019 31F0 XOR EAX,ESI EAX和ESI异或 003D001B EB 0C JMP SHORT 003D0029 跳到下面PUSH ECX那里 003D001D 33C8 XOR ECX,EAX 异或 003D001F EB 03 JMP SHORT 003D0024 跳到花指令,我们把0x0F改为90 003D0021 EB 09 JMP SHORT 003D002C 跳到XOR ESI,ESI那里ESI,清零 003D0023 90 NOP 003D0024 59 POP ECX 恢复ECX的值 003D0025 74 05 JE SHORT 003D002C ZF等于1就跳 003D0027 ^ 75 F8 JNZ SHORT 003D0021 ZF是0就向上跳转,跳到NOP上面那里 003D0029 51 PUSH ECX 保存ECX的值 003D002A ^ EB F1 JMP SHORT 003D001D 跳到上面XOR ECX,EAX那里 003D002C 33F6 XOR ESI,ESI ESI清零 003D002E E8 10000000 CALL 003D0043 现在开始学习大量的花指令了: 指令: 003D002C 33F6 XOR ESI,ESI 003D002E E8 10000000 CALL 003D0043 { 003D0041 C783 64FF3500 0>MOV DWORD PTR DS:[EBX+35FF64],64000000 003D004B 8925 00000000 MOV DWORD PTR DS:[0],ESP 003D0051 AD LODS DWORD PTR DS:[ESI] } 修改后的代码: 003D0041 90 NOP 003D0042 90 NOP 003D0043 64:FF35 0000000>PUSH DWORD PTR FS:[0] 003D004A 64:8925 0000000>MOV DWORD PTR FS:[0],ESP 003D0051 AD LODS DWORD PTR DS:[ESI] 003D0052 CD 20 INT 20 反跟踪代码 指令: 003D0054 68 9F6F56B6 PUSH B6566F9F 003D0059 50 PUSH EAX 003D005A E8 5D000000 CALL 003D00BC { 003D00BC 58 POP EAX 003D00BD EB FF JMP SHORT 003D00BE } 修改后: 003D00BC 58 POP EAX 003D00BD 90 NOP 003D00BE FFF0 PUSH EAX 003D00C0 EB FF JMP SHORT 003D00C1 指令: 003D00C0 /EB FF JMP SHORT 003D00C1 003D00C2 C083 E8FDEBFF 3>ROL BYTE PTR DS:[EBX+FFEBFDE8],30 ; 移位常量超出 1..31 的范围 003D00C9 E8 C9000000 CALL 003D0197 //受到前面指令的影响了 修改后: 003D00C0 90 NOP 003D00C1 FFC0 INC EAX 003D00C3 83E8 FD SUB EAX,-3 003D00C6 EB FF JMP SHORT 003D00C7 大家看出来没,双花指令 003D00C8 30E8 XOR AL,CH 修改后: 003D00C6 90 NOP 003D00C7 FF30 PUSH DWORD PTR DS:[EAX] 代码 003D00C7 FF30 PUSH DWORD PTR DS:[EAX] 003D00C9 E8 C9000000 CALL 003D0197 { 003D0196 ^\EB 83 JMP SHORT 003D011B 花指令 003D0198 C017 EB RCL BYTE PTR DS:[EDI],0EB ; 移位常量超出 1..31 的范 } 003D0196 90 NOP 003D0197 83C0 17 ADD EAX,17 修改后 花指令: 003D019A /EB FF JMP SHORT 003D019B 花 003D019C ^ 70 ED JO SHORT 003D018B 修改后: 003D019A 90 NOP 003D019B FF70 ED PUSH DWORD PTR DS:[EAX-13] 这个地方这里比较厉害,咋改都不对: 003D0081 /75 09 JNZ SHORT 003D008C 003D0083 |81F3 EBFF52BA XOR EBX,BA52FFEB 003D0089 |0100 ADD DWORD PTR DS:[EAX],EAX 003D008B |83EB FC SUB EBX,-4 003D008E 4A DEC EDX 003D008F FF71 0F PUSH DWORD PTR DS:[ECX+F] 哪位高人解释一下
当我们遇到的花指令比较多的时候,一定要按代码执行流程修改,不然看见一个就修改一个得话,会弄乱代码的