恩..首先我假设浏览这篇文章的你已经对PE结构非常熟悉,并且具备一定的编程功力.这样我才能说下去]
一. 做个压缩壳
0. 壳加载被保护/保护文件的流程
加:
读取文件->分析并XXOO操作->组装壳代码->建立文件头并添加一个节->把数据写入缓冲->生成文件
保护壳比压缩壳多的部分便是各种保护了,以最经常使用的SDK,窃取代码说明一下
通常在使用某个壳的SDK时,壳都会提供一个个成对出现的INC文件,他们通常都是
db 0xxh,0xxh,0xxh,0xxh 之类的,这就是壳在加上保护时确定你需要的功能以及定位
需要保护的代码所使用。简单的例子便是保护某个API或者某段函数。
其实他们只是在上面的流程中第二步里定位到那段DB xxx
保护API则是把CALL地址替换到壳代码在运行后的PE文件中的位置,API功能由壳实现
窃取代码相对复杂些,在搜索到后,把这段代码CUT下来,在壳中另外加密。
然后在这对标志的开头处添加一个JMP或者一个CALL。最常见的形式就是CALL
push 代码段标志,告诉壳应解密并执行那个参数
push 操作数,比如是不是执行后立即清除等等
call 壳处理这些SDK的代码位置
在完这样的代码后把数据移进缓冲[记得别把DB xxxx也复制过去了]
重复这样的操作后得到的便是保护后的代码了,记得重新计算下节大小
而类似 CopyMem 这样的保护则更复杂些,这样的保护利用的是自调试实现的
在收到一个读取或执行异常后分析异常,如果是特定的异常代码则把一段代码
解密并复制到内存,清理掉其他位置的代码然后让进程继续执行
但是这样的保护办法将会让进程的效率变的非常非常的差
话说我好象没见那个著名的壳主动的采用这样的保护
而检测Debuger则通常都是由壳的线程实现,当然在被保护进程代码段里插入检查Debug代码
也是经常被使用的方式,but 实际上要是在壳的 loader 部分不能搞定,线程检测和代码段里
进行检测也就没什么意义了。
解:
解压缩数据->把数据放回PE文件在内存中对应的节中->为PE文件加载DLL->填充IAT->跳回原入口
实际上你可以把自己的代码段在跳回原入口前清理掉,而对IAT加密则可以在填充IAT这一步进行。
最简单的办法就是:
在填充IAT的时候判断一下API的名称,如果是要保护的,则填入实现这个API功能函数在壳的地址
但是这样做并不能保护软件在脱壳后无法使用。仅仅是让ImportREC等重建导入表工具失效而已
1. 选择一个好的编译器
理论上,只要是能把你的代码编译成一堆16进制的编译器都能完成工作。
但是我还是推荐你使用以下三者之一
他们是, delphi 5的dcc32.exe, VC 8.0 的 cl.exe, masm 9.0 的 ml.exe
这系列的文章我将用 delphi 来完成所有的代码,原因和很多人讨厌 beign ... end 一样,我讨厌 {...}
2. 选择一种算法来使用
实际上,你可以采用任何的压缩算法,只要你乐意。
这一步的选择关键在于压缩算法的解压缩代码大小,
最符合这一条件的便是 APlib 了,他的解压代码仅仅 126 bytes。
当然可以不必要这样做,我们有更好的办法。
去掉下面这两句可以让APlib解压代码更小
sub edi,[esp+40]
mov [esp+28],edi
3. 壳代码需要些什么?
一个壳代码至少需要一个参数 原入口点,另至少需要五个API
GetProcAddress,LoadLibraryA 这两个API是用来加载被保护文件的导入表所使用
VirtualAlloc,VirtualFree 是用来解压缩时使用
pVirtualProtect 是用来修改PE头时使用
另外自己做GetProcAddress也是个相当好的办法,但是这会让壳体积变大
为了简单,我这里采用的方法是压缩整个文件的方式
知道了这些,我们就可以先开始制作自己的 Loader 了,完整的代码如下
这段代码在我的dcc32.exe编译后
全长度是 720 Bytes 减去解压缩代码的126 Bytes,我们的代码长度 594 Bytes
读取要压缩的文件头,增加一个节,并且把原来所有节的 SizeOfRawData,PointerToRawData改为0
自己建立一个导入表,复制导入表到Nt头结尾,并修改NT头导入表大小把RVA修改为新节的 VirtualAddress
提取原文件图标,把原文件整个压缩,然后复制图标数据到导入表结尾
修改Nt头的资源表位置RVA修改为新节的 VirtualAddress+导入表大小,把资源表大小修改为图标大小
把压缩后的数据复制到图标数据结尾,计算出压缩数据在新文件中的RVA。
把RVA写入到 壳的StartHere+0,大小写到 StartHere+4,然后修改自建导入表的 FirstTunkRva 到 StartHere+8
把修改好的壳代码复制到压缩数据的后面,根据所有数据的大小修改新节的 VirtualSize[注意对齐],SizeOfRawData
把新节的PointerToRawData修改为导入表在新文件中的Offset,最后把 AddressOfEntryPoint 写为壳 EP 的 RVA
[就是新节VirtualAddress+图标大小+导入表大小+DWORD(@EP)-DWORD(@StartHere)]
---------------------------------------------------------------------------------------------------------
OK,这样就完成了。试试能不能在 Part II 出来前自己完成他吧
恩,Part I 到这里就完结了,Part II 将是继续完成这个压缩壳的Packe部分,
Part III 则是如果在这个压缩壳的基础上加比较简单的 窃取代码
一. 做个压缩壳
0. 壳加载被保护/保护文件的流程
加:
读取文件->分析并XXOO操作->组装壳代码->建立文件头并添加一个节->把数据写入缓冲->生成文件
保护壳比压缩壳多的部分便是各种保护了,以最经常使用的SDK,窃取代码说明一下
通常在使用某个壳的SDK时,壳都会提供一个个成对出现的INC文件,他们通常都是
db 0xxh,0xxh,0xxh,0xxh 之类的,这就是壳在加上保护时确定你需要的功能以及定位
需要保护的代码所使用。简单的例子便是保护某个API或者某段函数。
其实他们只是在上面的流程中第二步里定位到那段DB xxx
保护API则是把CALL地址替换到壳代码在运行后的PE文件中的位置,API功能由壳实现
窃取代码相对复杂些,在搜索到后,把这段代码CUT下来,在壳中另外加密。
然后在这对标志的开头处添加一个JMP或者一个CALL。最常见的形式就是CALL
push 代码段标志,告诉壳应解密并执行那个参数
push 操作数,比如是不是执行后立即清除等等
call 壳处理这些SDK的代码位置
在完这样的代码后把数据移进缓冲[记得别把DB xxxx也复制过去了]
重复这样的操作后得到的便是保护后的代码了,记得重新计算下节大小
而类似 CopyMem 这样的保护则更复杂些,这样的保护利用的是自调试实现的
在收到一个读取或执行异常后分析异常,如果是特定的异常代码则把一段代码
解密并复制到内存,清理掉其他位置的代码然后让进程继续执行
但是这样的保护办法将会让进程的效率变的非常非常的差
话说我好象没见那个著名的壳主动的采用这样的保护
而检测Debuger则通常都是由壳的线程实现,当然在被保护进程代码段里插入检查Debug代码
也是经常被使用的方式,but 实际上要是在壳的 loader 部分不能搞定,线程检测和代码段里
进行检测也就没什么意义了。
解:
解压缩数据->把数据放回PE文件在内存中对应的节中->为PE文件加载DLL->填充IAT->跳回原入口
实际上你可以把自己的代码段在跳回原入口前清理掉,而对IAT加密则可以在填充IAT这一步进行。
最简单的办法就是:
在填充IAT的时候判断一下API的名称,如果是要保护的,则填入实现这个API功能函数在壳的地址
但是这样做并不能保护软件在脱壳后无法使用。仅仅是让ImportREC等重建导入表工具失效而已
1. 选择一个好的编译器
理论上,只要是能把你的代码编译成一堆16进制的编译器都能完成工作。
但是我还是推荐你使用以下三者之一
他们是, delphi 5的dcc32.exe, VC 8.0 的 cl.exe, masm 9.0 的 ml.exe
这系列的文章我将用 delphi 来完成所有的代码,原因和很多人讨厌 beign ... end 一样,我讨厌 {...}
2. 选择一种算法来使用
实际上,你可以采用任何的压缩算法,只要你乐意。
这一步的选择关键在于压缩算法的解压缩代码大小,
最符合这一条件的便是 APlib 了,他的解压代码仅仅 126 bytes。
当然可以不必要这样做,我们有更好的办法。
去掉下面这两句可以让APlib解压代码更小
sub edi,[esp+40]
mov [esp+28],edi
3. 壳代码需要些什么?
一个壳代码至少需要一个参数 原入口点,另至少需要五个API
GetProcAddress,LoadLibraryA 这两个API是用来加载被保护文件的导入表所使用
VirtualAlloc,VirtualFree 是用来解压缩时使用
pVirtualProtect 是用来修改PE头时使用
另外自己做GetProcAddress也是个相当好的办法,但是这会让壳体积变大
为了简单,我这里采用的方法是压缩整个文件的方式
知道了这些,我们就可以先开始制作自己的 Loader 了,完整的代码如下
这段代码在我的dcc32.exe编译后
全长度是 720 Bytes 减去解压缩代码的126 Bytes,我们的代码长度 594 Bytes
复制内容到剪贴板
这段代码的ASM则是这样,熟悉ASM的话可以看出还有很多的优化余地,有兴趣做个优化吗?
代码:
type
TRegs = record
Edi: Cardinal;
Esi: Cardinal;
Ebp: Cardinal;
Esp: Cardinal;
Ebx: Cardinal;
Edx: Cardinal;
Ecx: Cardinal;
Eax: Cardinal;
end;
function StartHere: PDWORD; assembler;//定位代码开始
asm
call @GetPointer
dd $FFFFFFFF //压缩后数据的位置
dd $FFFFFFFF //压缩后数据的大小
dd $FFFFFFFF //FUNC1 GetProcAddress
dd $FFFFFFFF //FUNC3 LoadLibraryA
dd $FFFFFFFF //FUNC4 VirtualAlloc
dd $FFFFFFFF //FUNC5 VirtualFree
dd $FFFFFFFF //FUNC5 VirtualProtect
dd 0
@GetPointer:
pop result
end;
procedure ApDepack(var Source, Destination); assembler;
asm
pushad
mov esi, Source
mov edi, Destination
cld
mov dl, 80h
xor ebx, ebx
@@literal:
movsb
mov bl, 2
@@nexttag:
call @@getbit
jnc @@literal
xor ecx, ecx
call @@getbit
jnc @@codepair
xor eax, eax
call @@getbit
jnc @@shortmatch
mov bl, 2
inc ecx
mov al, 10h
@@getmorebits:
call @@getbit
adc al, al
jnc @@getmorebits
jnz @@domatch
stosb
jmp @@nexttag
@@codepair:
call @@getgamma_no_ecx
sub ecx, ebx
jnz @@normalcodepair
call @@getgamma
jmp @@domatch_lastpos
@@shortmatch:
lodsb
shr eax, 1
jz @@donedepacking
adc ecx, ecx
jmp @@domatch_with_2inc
@@normalcodepair:
xchg eax, ecx
dec eax
shl eax, 8
lodsb
call @@getgamma
cmp eax, 32000
jae @@domatch_with_2inc
cmp ah, 5
jae @@domatch_with_inc
cmp eax, 7fh
ja @@domatch_new_lastpos
@@domatch_with_2inc:
inc ecx
@@domatch_with_inc:
inc ecx
@@domatch_new_lastpos:
xchg eax, ebp
@@domatch_lastpos:
mov eax, ebp
mov bl, 1
@@domatch:
push esi
mov esi, edi
sub esi, eax
rep movsb
pop esi
jmp @@nexttag
@@getbit:
add dl, dl
jnz @@stillbitsleft
mov dl, [esi]
inc esi
adc dl, dl
@@stillbitsleft:
ret
@@getgamma:
xor ecx, ecx
@@getgamma_no_ecx:
inc ecx
@@getgammaloop:
call @@getbit
adc ecx, ecx
call @@getbit
jc @@getgammaloop
ret
@@donedepacking:
popad
end;
function NextPChar(s:PChar):PChar;
begin
result:=s;
while PByte(result)^<>0 do inc(result);
inc(result);
end;
function NextDWORD(d:Pointer):PDWORD;
begin
result:=d;
inc(result);
end;
procedure Loader(Regs:TRegs); stdcall;
var
pGetProcAddress:function(hModule:HMODULE;lpProcName:LPCSTR):FARPROC;stdcall;
pLoadLibraryA:function(lpLibFileName:PChar):HMODULE;stdcall;
pVirtualAlloc:function(lpvAddress:Pointer;dwSize,flAllocationType,flProtect:DWORD):Pointer;stdcall;
pVirtualFree:function(lpAddress:Pointer;dwSize,dwFreeType:DWORD):BOOL;stdcall;
pVirtualProtect:function(lpAddress:Pointer;dwSize,flNewProtect:DWORD;lpflOldProtect:Pointer):BOOL;stdcall;
PFileHeader:PImageFileHeader;
POptHeader,POptHeader2:PImageOptionalHeader;
PSectionHead:PImageSectionHeader;
PDatDir,PDatDir2:PImageDataDirectory;
EPDATA,Buffer,pSrc,PDst,PImpTable:Pointer;
ImageBase,I,hDll,EPDATASIZE,hSize:Cardinal;
pName:PChar;
pFixThunkRva,pThunkRva,PFunc:PDWORD;
begin
//初始化参数
asm
mov eax,fs: [$30]
mov eax,[eax+$0c] //PEB
mov eax,[eax+$0c] //LDR
mov eax,[eax+$18] //ImageBase
mov ImageBase,eax //ImageBase
end;
PFunc:=StartHere;
EPDATA:=Pointer(ImageBase+PFunc^);
Inc(PFunc);
EPDATASIZE:=PFunc^;
Inc(PFunc);
pGetProcAddress:=Pointer(PFunc^);
Inc(PFunc);
pLoadLibraryA:=Pointer(PFunc^);
Inc(PFunc);
pVirtualAlloc:=Pointer(PFunc^);
Inc(PFunc);
pVirtualFree:=Pointer(PFunc^);
Inc(PFunc);
pVirtualProtect:=Pointer(PFunc^);
//分配缓冲并解压缩
Buffer:=pVirtualAlloc(nil,EPDATASIZE,MEM_COMMIT,PAGE_READWRITE);
ApDepack(EPDATA^,Buffer^);
//复制节数据到原来的位置
{$WARNINGS OFF}
PFileHeader:=PImageFileHeader(ImageBase+PImageDosHeader(ImageBase)^._lfanew+4);
{$WARNINGS ON}
POptHeader:=PImageOptionalHeader(DWORD(PFileHeader)+IMAGE_SIZEOF_FILE_HEADER);
PSectionHead:=PImageSectionHeader(DWORD(POptHeader)+IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
for I:=0 to PFileHeader^.NumberOfSections-1 do
begin
hSize:=PDWORD(DWORD(PSectionHead)+IMAGE_SIZEOF_SHORT_NAME)^;
if hSize>0 then
begin
pSrc:=Pointer(DWORD(ImageBase)+PSectionHead^.VirtualAddress);
pDst:=Pointer(DWORD(Buffer)+PSectionHead^.VirtualAddress);
asm
mov edi,pSrc
mov esi,pDst
mov ecx,hSize
rep movsb
end; //简单的CopyMemory到原来的地址
end;
Inc(PSectionHead);
end;
//重要的一步 IAT
{$WARNINGS OFF}
PFileHeader:=PImageFileHeader(DWORD(Buffer)+PImageDosHeader(Buffer)^._lfanew+4);
{$WARNINGS ON}
POptHeader2:=PImageOptionalHeader(DWORD(PFileHeader)+IMAGE_SIZEOF_FILE_HEADER);
PDatDir:=PImageDataDirectory(@POptHeader2^.DataDirectory[1]);
PImpTable:=Pointer(PDatDir^.VirtualAddress+DWORD(Buffer));
while DWORD(PImpTable^)<>0 do
begin
pThunkRva:=Pointer(DWORD(PImpTable)+$10); //得到原导入表的FirstThunk
pName:=Pointer(DWORD(EPDATA)+DWORD(pThunkRva)-4); //取得DLL名称
hDll:=pLoadLibraryA(pName); //加载DLL
pName:=NextPChar(pName); //移动到指向函数名
pFixThunkRva:=Pointer(ImageBase+DWORD(pThunkRva)); //被保护进程的IAT地址
while pThunkRva^<>0 do
begin
if PDWORD(pName)^ and $FFFF0000 = 0 then
begin
pFixThunkRva^:=DWORD(pGetProcAddress(hDll,Pointer(PWORD(pName)^)));
pName:=PChar(NextDWORD(pName));
end else begin
pFixThunkRva^:=DWORD(pGetProcAddress(hDll,pName));
pName:=NextPChar(pName);
end;
inc(pFixThunkRva); //下一个IA
inc(pThunkRva); //下一个IA
end;
PImpTable:=Pointer(DWORD(PImpTable)+20); //下一个导入表
end;
//把资源表重定向
pVirtualProtect(Pointer(ImageBase),$1000,PAGE_EXECUTE_READWRITE,@I); //使壳可写
PDatDir:=PImageDataDirectory(@POptHeader^.DataDirectory[2]);
PDatDir2:=PImageDataDirectory(@POptHeader2^.DataDirectory[2]);
PDatDir^.VirtualAddress:=PDatDir2^.VirtualAddress;
PDatDir^.Size:=PDatDir2^.Size;
//pVirtualProtect(Pointer(ImageBase),$1000,I,@I); //改回去,不用的话可以减少几BYTE
//使得下一个RET能返回到原入口
PDWORD(Regs.esp+SizeOf(TRegs))^:=ImageBase+POptHeader2^.AddressOfEntryPoint;
pVirtualFree(Buffer,0,MEM_RELEASE); //不释放也成,but...
end;
procedure EP;
asm
pushad
call Loader
popad
end;
procedure EndHere; assembler; asm end;//定位代码结束
复制内容到剪贴板
压缩壳的Packe部分,其实要做的已经不多了。仅仅是如下:
代码:
004085D4 $ 55 push ebp
004085D5 . 8BEC mov ebp, esp
004085D7 . 51 push ecx
004085D8 . E8 20000000 call 004085FD
004085DD FF db FF
004085DE FF db FF
004085DF FF db FF
004085E0 FF db FF
004085E1 FF db FF
004085E2 FF db FF
004085E3 FF db FF
004085E4 FF db FF
004085E5 FF db FF
004085E6 FF db FF
004085E7 FF db FF
004085E8 FF db FF
004085E9 FF db FF
004085EA FF db FF
004085EB FF db FF
004085EC FF db FF
004085ED FF db FF
004085EE FF db FF
004085EF FF db FF
004085F0 FF db FF
004085F1 FF db FF
004085F2 FF db FF
004085F3 FF db FF
004085F4 FF db FF
004085F5 FF db FF
004085F6 FF db FF
004085F7 FF db FF
004085F8 FF db FF
004085F9 00 db 00
004085FA 00 db 00
004085FB 00 db 00
004085FC 00 db 00
004085FD /$ 8F45 FC pop dword ptr [ebp-4]
00408600 |. 8B45 FC mov eax, dword ptr [ebp-4]
00408603 |. 59 pop ecx
00408604 |. 5D pop ebp
00408605 /. C3 retn
00408606 8BC0 mov eax, eax
00408608 $ 60 pushad
00408609 . 89C6 mov esi, eax
0040860B . 89D7 mov edi, edx
0040860D . FC cld
0040860E . B2 80 mov dl, 80
00408610 . 31DB xor ebx, ebx
00408612 > A4 movs byte ptr es:[edi], byte ptr [esi>
00408613 . B3 02 mov bl, 2
00408615 > E8 6D000000 call 00408687
0040861A .^ 73 F6 jnb short 00408612
0040861C . 31C9 xor ecx, ecx
0040861E . E8 64000000 call 00408687
00408623 . 73 1C jnb short 00408641
00408625 . 31C0 xor eax, eax
00408627 . E8 5B000000 call 00408687
0040862C . 73 23 jnb short 00408651
0040862E . B3 02 mov bl, 2
00408630 . 41 inc ecx
00408631 . B0 10 mov al, 10
00408633 > E8 4F000000 call 00408687
00408638 . 10C0 adc al, al
0040863A .^ 73 F7 jnb short 00408633
0040863C . 75 3F jnz short 0040867D
0040863E . AA stos byte ptr es:[edi]
0040863F .^ EB D4 jmp short 00408615
00408641 > E8 4D000000 call 00408693
00408646 . 29D9 sub ecx, ebx
00408648 . 75 10 jnz short 0040865A
0040864A . E8 42000000 call 00408691
0040864F . EB 28 jmp short 00408679
00408651 > AC lods byte ptr [esi]
00408652 . D1E8 shr eax, 1
00408654 . 74 4D je short 004086A3
00408656 . 11C9 adc ecx, ecx
00408658 . EB 1C jmp short 00408676
0040865A > 91 xchg eax, ecx
0040865B . 48 dec eax
0040865C . C1E0 08 shl eax, 8
0040865F . AC lods byte ptr [esi]
00408660 . E8 2C000000 call 00408691
00408665 . 3D 007D0000 cmp eax, 7D00
0040866A . 73 0A jnb short 00408676
0040866C . 80FC 05 cmp ah, 5
0040866F . 73 06 jnb short 00408677
00408671 . 83F8 7F cmp eax, 7F
00408674 . 77 02 ja short 00408678
00408676 > 41 inc ecx
00408677 > 41 inc ecx
00408678 > 95 xchg eax, ebp
00408679 > 89E8 mov eax, ebp
0040867B . B3 01 mov bl, 1
0040867D > 56 push esi
0040867E . 89FE mov esi, edi
00408680 . 29C6 sub esi, eax
00408682 . F3:A4 rep movs byte ptr es:[edi], byte ptr>
00408684 . 5E pop esi
00408685 .^ EB 8E jmp short 00408615
00408687 /$ 00D2 add dl, dl
00408689 |. 75 05 jnz short 00408690
0040868B |. 8A16 mov dl, byte ptr [esi]
0040868D |. 46 inc esi
0040868E |. 10D2 adc dl, dl
00408690 /> C3 retn
00408691 /$ 31C9 xor ecx, ecx
00408693 |$ 41 inc ecx
00408694 |> E8 EEFFFFFF /call 00408687
00408699 |. 11C9 |adc ecx, ecx
0040869B |. E8 E7FFFFFF |call 00408687
004086A0 |.^ 72 F2 /jb short 00408694
004086A2 /. C3 retn
004086A3 > 61 popad
004086A4 . C3 retn
004086A5 8D40 00 lea eax, dword ptr [eax]
004086A8 /$ EB 01 jmp short 004086AB
004086AA |> 40 /inc eax
004086AB |> 8038 00 cmp byte ptr [eax], 0
004086AE |.^ 75 FA /jnz short 004086AA
004086B0 |. 40 inc eax
004086B1 /. C3 retn
004086B2 8BC0 mov eax, eax
004086B4 /$ 83C0 04 add eax, 4
004086B7 /. C3 retn
004086B8 /$ 55 push ebp
004086B9 |. 8BEC mov ebp, esp
004086BB |. 83C4 C4 add esp, -3C
004086BE |. 53 push ebx
004086BF |. 56 push esi
004086C0 |. 57 push edi
004086C1 |. 64:8B05 30000>mov eax, dword ptr fs:[30]
004086C8 |. 8B40 0C mov eax, dword ptr [eax+C]
004086CB |. 8B40 0C mov eax, dword ptr [eax+C]
004086CE |. 8B40 18 mov eax, dword ptr [eax+18]
004086D1 |. 8945 FC mov dword ptr [ebp-4], eax
004086D4 |. E8 FBFEFFFF call 004085D4
004086D9 |. 8B10 mov edx, dword ptr [eax]
004086DB |. 0355 FC add edx, dword ptr [ebp-4]
004086DE |. 8955 D4 mov dword ptr [ebp-2C], edx
004086E1 |. 83C0 04 add eax, 4
004086E4 |. 8B08 mov ecx, dword ptr [eax]
004086E6 |. 83C0 04 add eax, 4
004086E9 |. 8B10 mov edx, dword ptr [eax]
004086EB |. 8955 EC mov dword ptr [ebp-14], edx
004086EE |. 83C0 04 add eax, 4
004086F1 |. 8B10 mov edx, dword ptr [eax]
004086F3 |. 8955 E8 mov dword ptr [ebp-18], edx
004086F6 |. 83C0 04 add eax, 4
004086F9 |. 8B10 mov edx, dword ptr [eax]
004086FB |. 83C0 04 add eax, 4
004086FE |. 8B18 mov ebx, dword ptr [eax]
00408700 |. 895D E4 mov dword ptr [ebp-1C], ebx
00408703 |. 83C0 04 add eax, 4
00408706 |. 8B00 mov eax, dword ptr [eax]
00408708 |. 8945 E0 mov dword ptr [ebp-20], eax
0040870B |. 6A 04 push 4
0040870D |. 68 00100000 push 1000
00408712 |. 51 push ecx
00408713 |. 6A 00 push 0
00408715 |. FFD2 call edx
00408717 |. 8945 D0 mov dword ptr [ebp-30], eax
0040871A |. 8B55 D0 mov edx, dword ptr [ebp-30]
0040871D |. 8B45 D4 mov eax, dword ptr [ebp-2C]
00408720 |. E8 E3FEFFFF call 00408608
00408725 |. 8B45 FC mov eax, dword ptr [ebp-4]
00408728 |. 33D2 xor edx, edx
0040872A |. 52 push edx
0040872B |. 50 push eax
0040872C |. 8B45 FC mov eax, dword ptr [ebp-4]
0040872F |. 8B40 3C mov eax, dword ptr [eax+3C]
00408732 |. 99 cdq
00408733 |. 030424 add eax, dword ptr [esp]
00408736 |. 135424 04 adc edx, dword ptr [esp+4]
0040873A |. 83C4 08 add esp, 8
0040873D |. 83C0 04 add eax, 4
00408740 |. 83D2 00 adc edx, 0
00408743 |. 8BD0 mov edx, eax
00408745 |. 8BC2 mov eax, edx
00408747 |. 83C0 14 add eax, 14
0040874A |. 8945 DC mov dword ptr [ebp-24], eax
0040874D |. 8B45 DC mov eax, dword ptr [ebp-24]
00408750 |. 05 E0000000 add eax, 0E0
00408755 |. 0FB752 02 movzx edx, word ptr [edx+2]
00408759 |. 4A dec edx
0040875A |. 85D2 test edx, edx
0040875C |. 72 3E jb short 0040879C
0040875E |. 42 inc edx
0040875F |. C745 C8 00000>mov dword ptr [ebp-38], 0
00408766 |> 8BC8 /mov ecx, eax
00408768 |. 83C1 08 |add ecx, 8
0040876B |. 8B09 |mov ecx, dword ptr [ecx]
0040876D |. 894D F0 |mov dword ptr [ebp-10], ecx
00408770 |. 837D F0 00 |cmp dword ptr [ebp-10], 0
00408774 |. 76 1D |jbe short 00408793
00408776 |. 8B48 0C |mov ecx, dword ptr [eax+C]
00408779 |. 034D FC |add ecx, dword ptr [ebp-4]
0040877C |. 894D F8 |mov dword ptr [ebp-8], ecx
0040877F |. 8B48 0C |mov ecx, dword ptr [eax+C]
00408782 |. 034D D0 |add ecx, dword ptr [ebp-30]
00408785 |. 894D F4 |mov dword ptr [ebp-C], ecx
00408788 |. 8B7D F8 |mov edi, dword ptr [ebp-8]
0040878B |. 8B75 F4 |mov esi, dword ptr [ebp-C]
0040878E |. 8B4D F0 |mov ecx, dword ptr [ebp-10]
00408791 |. F3:A4 |rep movs byte ptr es:[edi], byte pt>
00408793 |> 83C0 28 |add eax, 28
00408796 |. FF45 C8 |inc dword ptr [ebp-38]
00408799 |. 4A |dec edx
0040879A |.^ 75 CA /jnz short 00408766
0040879C |> 8B4D D0 mov ecx, dword ptr [ebp-30]
0040879F |. 8BC1 mov eax, ecx
004087A1 |. 33D2 xor edx, edx
004087A3 |. 52 push edx
004087A4 |. 50 push eax
004087A5 |. 8B45 D0 mov eax, dword ptr [ebp-30]
004087A8 |. 8B40 3C mov eax, dword ptr [eax+3C]
004087AB |. 99 cdq
004087AC |. 030424 add eax, dword ptr [esp]
004087AF |. 135424 04 adc edx, dword ptr [esp+4]
004087B3 |. 83C4 08 add esp, 8
004087B6 |. 83C0 04 add eax, 4
004087B9 |. 83D2 00 adc edx, 0
004087BC |. 8BD0 mov edx, eax
004087BE |. 83C2 14 add edx, 14
004087C1 |. 8955 D8 mov dword ptr [ebp-28], edx
004087C4 |. 8B45 D8 mov eax, dword ptr [ebp-28]
004087C7 |. 83C0 68 add eax, 68
004087CA |. 8B00 mov eax, dword ptr [eax]
004087CC |. 03C1 add eax, ecx
004087CE |. 8945 CC mov dword ptr [ebp-34], eax
004087D1 |. EB 70 jmp short 00408843
004087D3 |> 8B75 CC /mov esi, dword ptr [ebp-34]
004087D6 |. 83C6 10 |add esi, 10
004087D9 |. 8B5D D4 |mov ebx, dword ptr [ebp-2C]
004087DC |. 8BFE |mov edi, esi
004087DE |. 03DF |add ebx, edi
004087E0 |. 83EB 04 |sub ebx, 4
004087E3 |. 53 |push ebx
004087E4 |. FF55 E8 |call dword ptr [ebp-18]
004087E7 |. 8945 C4 |mov dword ptr [ebp-3C], eax
004087EA |. 8BC3 |mov eax, ebx
004087EC |. E8 B7FEFFFF |call 004086A8
004087F1 |. 8BD8 |mov ebx, eax
004087F3 |. 8B45 FC |mov eax, dword ptr [ebp-4]
004087F6 |. 03C7 |add eax, edi
004087F8 |. 8BF8 |mov edi, eax
004087FA |. EB 39 |jmp short 00408835
004087FC |> F703 0000FFFF |/test dword ptr [ebx], FFFF0000
00408802 |. 75 18 ||jnz short 0040881C
00408804 |. 0FB703 ||movzx eax, word ptr [ebx]
00408807 |. 50 ||push eax
00408808 |. 8B45 C4 ||mov eax, dword ptr [ebp-3C]
0040880B |. 50 ||push eax
0040880C |. FF55 EC ||call dword ptr [ebp-14]
0040880F |. 8907 ||mov dword ptr [edi], eax
00408811 |. 8BC3 ||mov eax, ebx
00408813 |. E8 9CFEFFFF ||call 004086B4
00408818 |. 8BD8 ||mov ebx, eax
0040881A |. EB 13 ||jmp short 0040882F
0040881C |> 53 ||push ebx
0040881D |. 8B45 C4 ||mov eax, dword ptr [ebp-3C]
00408820 |. 50 ||push eax
00408821 |. FF55 EC ||call dword ptr [ebp-14]
00408824 |. 8907 ||mov dword ptr [edi], eax
00408826 |. 8BC3 ||mov eax, ebx
00408828 |. E8 7BFEFFFF ||call 004086A8
0040882D |. 8BD8 ||mov ebx, eax
0040882F |> 83C7 04 ||add edi, 4
00408832 |. 83C6 04 ||add esi, 4
00408835 |> 833E 00 | cmp dword ptr [esi], 0
00408838 |.^ 75 C2 |/jnz short 004087FC
0040883A |. 8B45 CC |mov eax, dword ptr [ebp-34]
0040883D |. 83C0 14 |add eax, 14
00408840 |. 8945 CC |mov dword ptr [ebp-34], eax
00408843 |> 8B45 CC mov eax, dword ptr [ebp-34]
00408846 |. 8338 00 |cmp dword ptr [eax], 0
00408849 |.^ 75 88 /jnz short 004087D3
0040884B |. 8D45 C8 lea eax, dword ptr [ebp-38]
0040884E |. 50 push eax
0040884F |. 6A 40 push 40
00408851 |. 68 00100000 push 1000
00408856 |. 8B45 FC mov eax, dword ptr [ebp-4]
00408859 |. 50 push eax
0040885A |. FF55 E0 call dword ptr [ebp-20]
0040885D |. 8B45 DC mov eax, dword ptr [ebp-24]
00408860 |. 83C0 70 add eax, 70
00408863 |. 8B55 D8 mov edx, dword ptr [ebp-28]
00408866 |. 83C2 70 add edx, 70
00408869 |. 8B0A mov ecx, dword ptr [edx]
0040886B |. 8908 mov dword ptr [eax], ecx
0040886D |. 8B52 04 mov edx, dword ptr [edx+4]
00408870 |. 8950 04 mov dword ptr [eax+4], edx
00408873 |. 8B45 D8 mov eax, dword ptr [ebp-28]
00408876 |. 8B40 10 mov eax, dword ptr [eax+10]
00408879 |. 0345 FC add eax, dword ptr [ebp-4]
0040887C |. 8B55 14 mov edx, dword ptr [ebp+14]
0040887F |. 83C2 20 add edx, 20
00408882 |. 8902 mov dword ptr [edx], eax
00408884 |. 68 00800000 push 8000
00408889 |. 6A 00 push 0
0040888B |. 8B45 D0 mov eax, dword ptr [ebp-30]
0040888E |. 50 push eax
0040888F |. FF55 E4 call dword ptr [ebp-1C]
00408892 |. 5F pop edi
00408893 |. 5E pop esi
00408894 |. 5B pop ebx
00408895 |. 8BE5 mov esp, ebp
00408897 |. 5D pop ebp
00408898 /. C2 2000 retn 20
0040889B 90 nop ; |
0040889C . 60 pushad ; |
0040889D . E8 16FEFFFF call 004086B8 ; /test.004086B8
004088A2 . 61 popad
004088A3 . C3 retn
读取要压缩的文件头,增加一个节,并且把原来所有节的 SizeOfRawData,PointerToRawData改为0
自己建立一个导入表,复制导入表到Nt头结尾,并修改NT头导入表大小把RVA修改为新节的 VirtualAddress
提取原文件图标,把原文件整个压缩,然后复制图标数据到导入表结尾
修改Nt头的资源表位置RVA修改为新节的 VirtualAddress+导入表大小,把资源表大小修改为图标大小
把压缩后的数据复制到图标数据结尾,计算出压缩数据在新文件中的RVA。
把RVA写入到 壳的StartHere+0,大小写到 StartHere+4,然后修改自建导入表的 FirstTunkRva 到 StartHere+8
把修改好的壳代码复制到压缩数据的后面,根据所有数据的大小修改新节的 VirtualSize[注意对齐],SizeOfRawData
把新节的PointerToRawData修改为导入表在新文件中的Offset,最后把 AddressOfEntryPoint 写为壳 EP 的 RVA
[就是新节VirtualAddress+图标大小+导入表大小+DWORD(@EP)-DWORD(@StartHere)]
---------------------------------------------------------------------------------------------------------
OK,这样就完成了。试试能不能在 Part II 出来前自己完成他吧
恩,Part I 到这里就完结了,Part II 将是继续完成这个压缩壳的Packe部分,
Part III 则是如果在这个压缩壳的基础上加比较简单的 窃取代码