牺牲色相,再来一个Code injection的,适用于V2的现有的全部版本
BTW:老王那BT可能过不了多久会下杀令了:-),应该会有新的版本让这种方法枪B.
附件:EPEV2code in.rar
EPE V2 CODE Injection
【目 标】:随便你自己去加个就行了
【工 具】:Olydbg1.1(diy版)、LORDPE,WINHEX
【任 务】:不脱壳注入pj代码
【操作平台】:Windows 2003 server
【作 者】: LOVEBOOM[DFCG][FCG][US]
【相关链接】: www.encryptpe.com
【简要说明】: EPE V2的反调试和加密功能比2003可说是强了很多。这次我来一次不脱壳直接通过注入代码修改原程序流程。通过代码注入绕过EPE的注册认证。这个问题我已经和老王说过了,不久后应该会解决这个问题的:_)。我这篇只讲service的加壳方式,此方法也可以用于普通的加密方式,因为考虑有关问题,我不打算写出来。我选用epe2004810做为目标,关于这个可以很方便的注入的原因老王说了是为了方便有的客户加多层壳。看来做什么,怎么做都是有难的地方。
【详细过程】:
首先强烈建议各位对这个壳有一定了解,对PE知识有点了解,知道怎么用OD修改保存代码,并且会脱EPE V22004810的朋友再看这篇文章,至于epev2的脱壳,可以参考FLY或是我的for 2005314的文章,情况是差不多的。这篇文章里不会告诉你如何去找CRC处,CRC处在我的2005的那篇文章里有写.因为这个壳是通过注入壳的DLL到explorer时里,所以如果你的patch后程序运行之前你的系统已经加载了DLL,这个注入方法将会失败(当然,用其它方法还是可以注入的,方法也不难,自己想想就会了。)。
用OD载入目标,设置忽略全部异常,按epe v20053.14的方法可以很快速的定位到CRC检测和两个注册检测点,找到的结果:
CRC的两个地方:
711E3792 B0 00 MOV AL,0 ;crc check这里是修改后的
......
711E501D 0F95C0 SETNE AL ;crc check
711E5020 5F POP EDI
711E5021 5E POP ESI
注册的两个地方:
711E2C4B 8B83 00030000 MOV EAX,DWORD PTR DS:[EBX+300]
711E2C51 8378 0C 01 CMP DWORD PTR DS:[EAX+C],1 ;这里必须为0([EAX+C]==0跳过注册)
711E2C55 75 22 JNZ SHORT 711E2C79 ;如果不要注册则跳
......
711E2C85 8B83 24030000 MOV EAX,DWORD PTR DS:[EBX+324]
711E2C8B 8378 30 64 CMP DWORD PTR DS:[EAX+30],64 ;这里不能为64正常应该是65([EAX+30]<>64跳过注册)
711E2C8F 75 0A JNZ SHORT 711E2C9B
Ok再次载入目标,F9运行几秒钟,F12暂停然后执行到解压壳代码处,因为壳是DLL的所以要向上找到判断是否已经解压的代码直接向上找到:
71236C90 > 807C24 08 01 CMP BYTE PTR SS:[ESP+8],1
71236C95 0F85 91010000 JNZ 71236E2C ; 这里判断,如果解压完了则跳
好了,先记下这个地址,向下找到跳过壳入口的代码:
71236E2B 61 POPAD ; 这里开始改成我们自己的patch代码
71236E2C ^ E9 73E5FAFF JMP 711E53A4
跟踪发现如果DLL没有载入的话每次都会强行生成一个生的DLL文件,下面我们就来看看它是怎么样生成的,重来一遍分析一下:
0044E000 > 60 PUSHAD ; EP
0044E001 9C PUSHFD
0044E002 64:FF35 0000000>PUSH DWORD PTR FS:[0]
0044E009 E8 7A010000 CALL 0044E188 ; 这里f7跟进
……
进来后分析如下:
0044E188 5D POP EBP ; CDD1+5cr.0044E00E
0044E189 68 04010000 PUSH 104 ; /Buffer Size ==104
0044E18E 89E8 MOV EAX,EBP ; |
0044E190 83C0 4C ADD EAX,4C ; |
0044E193 50 PUSH EAX ; |Buffer
0044E194 89E8 MOV EAX,EBP ; |
0044E196 83C0 28 ADD EAX,28 ; |
0044E199 FF10 CALL DWORD PTR DS:[EAX] ; \API Function Get SystemDirectoryA
0044E19B 83F8 04 CMP EAX,4 ; 如果路径长度小于4则over
0044E19E 0F8C 1F010000 JL <ExitProcess>
0044E1A4 89C1 MOV ECX,EAX
0044E1A6 89E8 MOV EAX,EBP
0044E1A8 83C0 4C ADD EAX,4C
0044E1AB 8A5401 FF MOV DL,BYTE PTR DS:[ECX+EAX-1] ; 判断路径是否以\结束
0044E1AF 80FA 5C CMP DL,5C
0044E1B2 74 06 JE SHORT <@F>
0044E1B4 41 INC ECX ; 如果不是则加上\
0044E1B5 C64401 FF 5C MOV BYTE PTR DS:[ECX+EAX-1],5C
0044E1BA > 89C3 MOV EBX,EAX
0044E1BC 81C3 05010000 ADD EBX,105
0044E1C2 01C8 ADD EAX,ECX
0044E1C4 31C9 XOR ECX,ECX
0044E1C6 8A1419 MOV DL,BYTE PTR DS:[ECX+EBX] ; 连接成完整的DLL名
0044E1C9 881401 MOV BYTE PTR DS:[ECX+EAX],DL
0044E1CC 80FA 00 CMP DL,0
0044E1CF 74 03 JE SHORT <Do next> ; 生成了完整的DLL名则跳
0044E1D1 41 INC ECX
0044E1D2 ^ EB F2 JMP SHORT 0044E1C6
0044E1D4 > 6A 00 PUSH 0 ; /hTemplateFile = NULL
0044E1D6 68 80000000 PUSH 80 ; |Attributes = NORMAL
0044E1DB 6A 04 PUSH 4 ; |Mode = OPEN_ALWAYS
0044E1DD 6A 00 PUSH 0 ; |pSecurity = NULL
0044E1DF 6A 00 PUSH 0 ; |ShareMode = 0
0044E1E1 68 000000C0 PUSH C0000000 ; |Access = GENERIC_READ|GENERIC_WRITE
0044E1E6 89E8 MOV EAX,EBP ; |
0044E1E8 83C0 4C ADD EAX,4C ; |
0044E1EB 50 PUSH EAX ; |FileName = "C:\WINDOWS\system32\V22004810.EPE"
0044E1EC 89E8 MOV EAX,EBP ; |
0044E1EE 83C0 2C ADD EAX,2C ; |
0044E1F1 FF10 CALL DWORD PTR DS:[EAX] ; \CreateFileA
0044E1F3 83F8 FF CMP EAX,-1 ; 如果返回-1则表明DLL已经加载,如果文件不存在则会新建一个
0044E1F6 0F84 86000000 JE <LoadLibrary Proc> ; 如果目标DLL已经加载则跳去直接GetProcess
0044E1FC 89C3 MOV EBX,EAX
0044E1FE 6A 00 PUSH 0 ; /MapName = NULL
0044E200 89E8 MOV EAX,EBP ; |
0044E202 05 71010000 ADD EAX,171 ; |
0044E207 8B08 MOV ECX,DWORD PTR DS:[EAX] ; |
0044E209 51 PUSH ECX ; |MaximumSizeLow = 6B200
0044E20A 6A 00 PUSH 0 ; |MaximumSizeHigh = 0
0044E20C 6A 04 PUSH 4 ; |Protection = PAGE_READWRITE
0044E20E 6A 00 PUSH 0 ; |pSecurity = NULL
0044E210 53 PUSH EBX ; |hFile = 00000014 (window)
0044E211 89E8 MOV EAX,EBP ; |
0044E213 83C0 30 ADD EAX,30 ; |
0044E216 FF10 CALL DWORD PTR DS:[EAX] ; \CreateFileMappingA
0044E218 83F8 00 CMP EAX,0
0044E21B 74 5D JE SHORT <CloseHandleProc> ; 如果操作失败则跳去直接GetProcess
0044E21D 89C6 MOV ESI,EAX ; hMem
0044E21F 89E8 MOV EAX,EBP
0044E221 05 71010000 ADD EAX,171
0044E226 8B08 MOV ECX,DWORD PTR DS:[EAX]
0044E228 51 PUSH ECX ; /MapSize = 6B200 (438784.)
0044E229 6A 00 PUSH 0 ; |OffsetLow = 0
0044E22B 6A 00 PUSH 0 ; |OffsetHigh = 0
0044E22D 68 1F000F00 PUSH 0F001F ; |AccessMode = F001F
0044E232 56 PUSH ESI ; |hMapObject = 0000001C
0044E233 89E8 MOV EAX,EBP ; |
0044E235 83C0 34 ADD EAX,34 ; |
0044E238 FF10 CALL DWORD PTR DS:[EAX] ; \MapViewOfFile
0044E23A 83F8 00 CMP EAX,0
0044E23D 74 33 JE SHORT <CloseHandleProc> ; 如果操作失败则跳
0044E23F 50 PUSH EAX
0044E240 89C7 MOV EDI,EAX
0044E242 89E8 MOV EAX,EBP
0044E244 05 71010000 ADD EAX,171
0044E249 8B08 MOV ECX,DWORD PTR DS:[EAX]
0044E24B 83F9 00 CMP ECX,0
0044E24E 74 1B JE SHORT <UnmapViewOfFileProc> ; 如果大小为0则跳
0044E250 51 PUSH ECX ; 开始循环解压出代码
0044E251 8B48 04 MOV ECX,DWORD PTR DS:[EAX+4]
0044E254 8A70 08 MOV DH,BYTE PTR DS:[EAX+8] ; 这里关键取出关键KEY(28)
0044E257 83C0 09 ADD EAX,9
0044E25A 01C8 ADD EAX,ECX
0044E25C 59 POP ECX
0044E25D > 8A10 MOV DL,BYTE PTR DS:[EAX] ; eax==开始解压的地址,44E2CC
0044E25F 32D6 XOR DL,DH ; Decrypt =KEY (28) xor Encrypted code
0044E261 8817 MOV BYTE PTR DS:[EDI],DL ; 保存正确的代码到mem中
0044E263 40 INC EAX
0044E264 47 INC EDI
0044E265 49 DEC ECX
0044E266 83F9 00 CMP ECX,0
0044E269 ^ 75 F2 JNZ SHORT <Loop Decrypt>
0044E26B > 89E8 MOV EAX,EBP
0044E26D 83C0 38 ADD EAX,38
0044E270 FF10 CALL DWORD PTR DS:[EAX] ; UnmapViewOfFile
0044E272 > 56 PUSH ESI ; /hObject==1c
0044E273 89E8 MOV EAX,EBP ; |
0044E275 83C0 3C ADD EAX,3C ; |
0044E278 FF10 CALL DWORD PTR DS:[EAX] ; \CloseHandle
0044E27A > 53 PUSH EBX ; /hObject
0044E27B 89E8 MOV EAX,EBP ; |
0044E27D 83C0 3C ADD EAX,3C ; |
0044E280 FF10 CALL DWORD PTR DS:[EAX] ; \CloseHandle
0044E282 > 89E8 MOV EAX,EBP
0044E284 83C0 4C ADD EAX,4C
0044E287 50 PUSH EAX ; /FileName = "C:\WINDOWS\system32\V22004810.EPE"
0044E288 89E8 MOV EAX,EBP ; |
0044E28A 83C0 40 ADD EAX,40 ; |
0044E28D FF10 CALL DWORD PTR DS:[EAX] ; \LoadLibraryA
0044E28F 83F8 00 CMP EAX,0 ; 如果载入DLL失败则OVER
0044E292 74 2F JE SHORT <ExitProcess>
0044E294 89C3 MOV EBX,EAX ; EAX=hmodule
0044E296 89E8 MOV EAX,EBP
0044E298 05 62010000 ADD EAX,162 ; 准备获取Encrypt_Init的地址
0044E29D 50 PUSH EAX ; /ProcNameOrOrdinal = "EncryptPE_Init"
0044E29E 53 PUSH EBX ; |hModule = 71120000 (V2200481)
0044E29F 89E8 MOV EAX,EBP ; |
0044E2A1 83C0 44 ADD EAX,44 ; |
0044E2A4 FF10 CALL DWORD PTR DS:[EAX] ; \GetProcAddress
0044E2A6 83F8 00 CMP EAX,0 ; 如果获取函数失败则over
0044E2A9 74 18 JE SHORT <ExitProcess>
0044E2AB 89C3 MOV EBX,EAX
0044E2AD 89E8 MOV EAX,EBP
0044E2AF 05 71010000 ADD EAX,171
0044E2B4 8B08 MOV ECX,DWORD PTR DS:[EAX]
0044E2B6 8B50 04 MOV EDX,DWORD PTR DS:[EAX+4]
0044E2B9 83C0 09 ADD EAX,9
0044E2BC 01D0 ADD EAX,EDX
0044E2BE 01C8 ADD EAX,ECX
0044E2C0 50 PUSH EAX ; /Decrypt address
0044E2C1 FFD3 CALL EBX ; \Call DecryptCode
0044E2C3 > 6A 00 PUSH 0 ; /Exit Code ==0
0044E2C5 89E8 MOV EAX,EBP ; |
0044E2C7 83C0 48 ADD EAX,48 ; |
0044E2CA FF10 CALL DWORD PTR DS:[EAX] ; \Exit Process
0044E2CC 65:72 78 JB SHORT 0044E347 ; 这里开始就是壳程序加密后的代码存放处
0044E2CF 282A SUB BYTE PTR DS:[EDX],CH
0044E2D1 2828 SUB BYTE PTR DS:[EAX],CH
通过分析现在已经得到KEY为28,现在通过计算可以知道跳去壳OEP的代码存放在address:4b84f7 RAW:6AAF7处,判断是否已经加载的代码大概在: address:4B8363 RAW: 6A963处.下面就剩下写patch代码了:
71236E2B E8 00000000 CALL 71236E30 ; 用于后面定位具体地址
71236E30 58 POP EAX
71236E31 8BD8 MOV EBX,EAX
71236E33 2D 9E360500 SUB EAX,5369E
71236E38 E8 30000000 CALL 71236E6D ; 去除711E3792处的CRC检测
71236E3D 8BC3 MOV EAX,EBX
71236E3F 2D 131E0500 SUB EAX,51E13
71236E44 E8 24000000 CALL 71236E6D ; 去除711E501D 处的CRC检测
71236E49 2D D2230000 SUB EAX,23D2
71236E4E 8BD3 MOV EDX,EBX
71236E50 83C2 58 ADD EDX,58
71236E53 E8 20000000 CALL 71236E78 ; patch代码去除注册判断点一
71236E58 83C0 3A ADD EAX,3A
71236E5B 8BD3 MOV EDX,EBX
71236E5D 83C2 68 ADD EDX,68
71236E60 E8 13000000 CALL 71236E78 ; PATCH代码去除注册判断点二
71236E65 61 POPAD
71236E66 ^ E9 39E5FAFF JMP 711E53A4 ; 修改完毕,执行原壳代码
71236E6B 90 NOP
71236E6C 90 NOP
71236E6D 66:C700 B000 MOV WORD PTR DS:[EAX],0B0 ; 两个crc处都改为mov bl,0
71236E72 C640 02 90 MOV BYTE PTR DS:[EAX+2],90
71236E76 C3 RETN
71236E77 90 NOP
71236E78 2BD0 SUB EDX,EAX ; 计算跳转的距离
71236E7A 83EA 06 SUB EDX,6
71236E7D 66:C700 90E8 MOV WORD PTR DS:[EAX],0E890
71236E82 8950 02 MOV DWORD PTR DS:[EAX+2],EDX ; 修改地址
71236E85 C3 RETN
71236E86 90 NOP
71236E87 90 NOP
71236E88 8B83 00030000 MOV EAX,DWORD PTR DS:[EBX+300] ; patch注册点一
71236E8E C740 0C 0000000>MOV DWORD PTR DS:[EAX+C],0
71236E95 C3 RETN
71236E96 90 NOP
71236E97 90 NOP
71236E98 8B83 24030000 MOV EAX,DWORD PTR DS:[EBX+324] ; patch注册点二
71236E9E C740 30 6500000>MOV DWORD PTR DS:[EAX+30],65
71236EA5 C3 RETN
写完这代码再写几行加密代码,然后把代码保存到相关位置即可。
加密代码:
mov ecx,size
mov edi,offset startaddr
@@:
mov al,byte ptr [edi]
xor al,28h
stosb
dec ecx
jnz @B
计算后和得出加密后的数据,然后用winhex放到相关位置,保存,再运行试试,如何,是的你成功了。
Greetz:
Fly.Jingulong,yock,tDasm.David.hexer,hmimys,ahao.UFO(brother).alan(sister).all of my friends and you!
By loveboom[DFCG][FCG][US]
http://blog.csdn.net/bmd2chen
Email:loveboom#163.com
Date:5/22/2005 9:51:00 PM
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)