前提假设您已经有了一定的PE Virus的知识.
好了~先简单的说说无导入表程序的几点基本的构成
1.GetkernelBase(获取kernel32.dll的基址)
由于我们是无导入表的程序所以,所有API函数都是依靠内存搜索完成的,
想必大家已经知道EXE载入到内存中ESP保存ExitThread函数地址
ExitThread函数是在kernel32.dll 模块中的,所以证明EXE载入的时候就已经加载
了kernel32.dll模块,于是我们的
工作就是确定kernel32.dll的基址。
这里我使用"PEB获取地址kernel32.dll基址"的方法(简单嘛。。Delphi调试这种程序很麻烦的~所以使用这个。。)
代码:--------------------------------------------------------------------------------
asm
mov eax,fs:$30
mov eax,[eax + $0c]
mov esi,[eax + $1c]
lodsd
mov eax,[eax+$08] //这个时候eax中保存的就是k32的基址了
end;
--------------------------------------------------------------------------------
基址获取到了剩下的就是需要确定我们需要的两个重要的函数
"GetProcAddress"和"LoadLibraryA"两个函数~有了这两个函数我们就可以
获取到我们需要的任何函数了..
2.自构建"GetProcAddress"函数
上面我们已经获取到k32的基址了~但是
问题是我们还需要一些其他函数来完成我们程序
的功能,首先我们回顾一下~前辈们写的API搜索函数,为了减少
程序体积和保护程序自身
他们基本上都是使用hash值来搜索模块的导入表的,这样我们就可以自己构建一个API
搜索 函数了。直接贴代码好了~其实
Delphi版本的API搜索函数许多前辈都写过
Aming,老王,liumazi等等~
代码:--------------------------------------------------------------------------------
FUNCTION GetProcAddress(Module:Cardinal;ProcessCRC:DWORD) : Pointer;
VAR
ExportName : pChar;
Address : Cardinal;
J : Cardinal;
ImageDosHeader : PImageDosHeader;
ImageNTHeaders : PImageNTHeaders;
ImageExportDirectory : PImageExportDirectory;
BEGIN
ImageDosHeader:=Pointer(Module);
ImageNTHeaders:=Pointer(Module+ImageDosHeader._lfanew);
ImageExportDirectory:=Pointer(ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress+Module);
J:=0;
Address:=0;
REPEAT
ExportName:=Pointer(Cardinal(Pointer(Cardinal(ImageExportDirectory.AddressOfNames)+Module+J*4)^)+Module);
IF CalculateCRC32(ExportName^,StrLen(ExportName))=ProcessCRC THEN
Address:=Cardinal(Pointer(Word(Pointer(J SHL 1+Cardinal(
ImageExportDirectory.AddressOfNameOrdinals)+Module)^) AND
$0000FFFF SHL 2+Cardinal(ImageExportDirectory.AddressOfFunctions)
+Module)^)+Module;
Inc(J);
UNTIL (Address<>0)OR(J=ImageExportDirectory.NumberOfNames);
Result:=Pointer(Address);
END;
----------------------------------
----------------------------------------------
好了~此函数就可以帮我们,循环对比ProcessCRC参数中给出的API的hash值
然后发挥这个函数的地址,我这里使用的是Crc32算法~
上面的PE的数据结构可以从Windows中Copy出来
代码:--------------------------------------------------------------------------------
PROCEDURE BuildCRC32Table; ASSEMBLER;
ASM
mov ebx, 0EDB88320h
lea edi, crc32tab
xor ecx, ecx
@loc1:
mov eax, ecx
mov edx, 8
@loc2:
test eax, 1
jz @loc3
shr eax, 1
xor eax, ebx
jmp @loc4
@loc3:
shr eax, 1
@loc4:
dec edx
jnz @loc2
stosd
inc ecx
cmp ecx, 256
jb @loc1
END;
FUNCTION CalculateCRC32(VAR Buffer;CONST Size:DWORD) : DWORD; ASSEMBLER;
ASM
push esi
push edi
push ebx
mov edi,edx
mov esi