金笛工业手机论坛  

返回   金笛工业手机论坛 > 开发者乐园 > 短信开发资料

短信开发资料 短信开发技巧,代码分析

回复
 
LinkBack 主题工具 显示模式
旧 2009-10-26   #1 (permalink)
高级会员
 
注册日期: 2009-07-09
住址: 亦庄经济开发区2号院大族广场1502
帖子: 531
susu8988 正向着好的方向发展
默认 Delphi下构建无导入表程序--使用hash获取API

前提假设您已经有了一定的PEVirus的知识.
好了~先简单的说说无导入表程序的几点基本的构成
1.GetkernelBase(获取kernel32.dll的基址)
由于我们是无导入表的程序所以,所有API函数都是依靠内存搜索完成的,
想必大家已经知道EXE载入到内存中ESP保存ExitThread函数地址
ExitThread函数是在kernel32.dll模块中的,所以证明EXE载入的时候就已经加载
了kernel32.dll模块,于是我们的工作就是确定kernel32.dll的基址。

这里我使用"PEB获取地址kernel32.dll基址"的方法(简单嘛。。Delphi调试这种程序很麻烦的~所以使用这个。。)

代码:--------------------------------------------------------------------------------
asm
moveax,fs:$30
moveax,[eax+$0c]
movesi,[eax+$1c]
lodsd
moveax,[eax+$08]//这个时候eax中保存的就是k32的基址了
end;
--------------------------------------------------------------------------------
基址获取到了剩下的就是需要确定我们需要的两个重要的函数
"GetProcAddress"和"LoadLibraryA"两个函数~有了这两个函数我们就可以
获取到我们需要的任何函数了..

2.自构建"GetProcAddress"函数
上面我们已经获取到k32的基址了~但是问题是我们还需要一些其他函数来完成我们程序
的功能,首先我们回顾一下~前辈们写的API搜索函数,为了减少程序体积和保护程序自身
他们基本上都是使用hash值来搜索模块的导入表的,这样我们就可以自己构建一个API搜索
函数了。直接贴代码好了~其实Delphi版本的API搜索函数许多前辈都写过
Aming,老王,liumazi等等~

代码:--------------------------------------------------------------------------------
FUNCTIONGetProcAddress(Module:Cardinal;ProcessCRCWORD):Pointer;
VAR
ExportNameChar;
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);
IFCalculateCRC32(ExportName^,StrLen(ExportName))=ProcessCRCTHEN
Address:=Cardinal(Pointer(Word(Pointer(JSHL1+Cardinal(
ImageExportDirectory.AddressOfNameOrdinals)+Module)^)AND
$0000FFFFSHL2+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出来


代码:--------------------------------------------------------------------------------
PROCEDUREBuildCRC32Table;ASSEMBLER;
ASM
movebx,0EDB88320h
leaedi,crc32tab
xorecx,ecx
@loc1:
moveax,ecx
movedx,8
@loc2:
testeax,1
jz@loc3
shreax,1
xoreax,ebx
jmp@loc4
@loc3:
shreax,1
@loc4:
decedx
jnz@loc2
stosd
incecx
cmpecx,256
jb@loc1
END;

FUNCTIONCalculateCRC32(VARBuffer;CONSTSizeWORD)WORD;ASSEMBLER;
ASM
pushesi
pushedi
pushebx
movedi,edx
movesi,eax
xorebx,ebx
moveax,$ffffffff
movecx,edi
shrecx,2
jecxz@Rest
@Loop:
movedx,[esi]
movbl,al
xorbl,dl
shreax,8
xoreax,dwordptr[CRC32tab+ebx*4]
movbl,al
xorbl,dh
shreax,8
xoreax,dwordptr[CRC32tab+ebx*4]
shredx,16
movbl,al
xorbl,dl
shreax,8
xoreax,dwordptr[CRC32tab+ebx*4]
movbl,al
xorbl,dh
shreax,8
xoreax,dwordptr[CRC32tab+ebx*4]
addesi,4
loop@Loop
@Rest:
movecx,edi
andecx,3
jecxz@End
@Loop_Rest:
movbl,al
xorbl,[esi]
shreax,8
incesi
xoreax,dwordptr[CRC32tab+ebx*4]
loop@Loop_Rest
@End:
xoreax,$ffffffff
popebx
popedi
popesi
END;
--------------------------------------------------------------------------------
这个是计算一个数据的Crc32数值--返回是10进制的~可以自己改变成16进制

好了现在我们已经有了GetProcAddress函数了~好像还少一个??
前面我们提到过需要两个函数~GetProcAddress有了·k32的基址也有了
这样我们就可以搜索出LoadLibraryA的地址....
好了完成前面的代码

代码:--------------------------------------------------------------------------------
FUNCTIONMyLoadLibraryA:Pointer;
const
MyLoadLibraryA=$3FC1BD8D;//LoadLibraryA的Crc32数值
asm
moveax,fs:$30
moveax,[eax+$0c]
movesi,[eax+$1c]
lodsd
moveax,[eax+$08]//此时eax中就保存了k32的基址
movedx,MyLoadLibraryA//压入LoadLibraryA的Hash
callGetProcAddress//开始获取LoadLibraryA的地址
end;
--------------------------------------------------------------------------------

好了现在我们两个函数都有了~现在我们的任务已经完成一半了!
(为什么是一半??因为Delphi非等同于VC和XXXASM,他不能够自己构建PE结构)
准确的说~即使你写一个只有一条beginend.的程序~编译器编译的时候还是会连接N多
的API函数~进来....
为了完成任务,我们这里就使用了NicoBendlin前辈的miniEXE的模板...
自己打造了一个无导入表的程序...
这里需要我们自己编译system.pas和SysInit.pas单元

代码:--------------------------------------------------------------------------------
//SysInit.pas单元代码
unitSysInit;

interface

var
TlsIndex:LongWord;

implementation

end.
--------------------------------------------------------------------------------
System.pas单元代码

代码:--------------------------------------------------------------------------------
unitSystem;

interface

type
DWORD=LongWord;
PLongWord=^LongWord;
PWord=^Word;
TGUID=record
D1:LongWord;
D2:Word;
D3:Word;
D4:array[0..7]ofByte;
end;

const
Kernel32='kernel32.dll'

var
ExitCode:LongWord;
HKernel32:LongWord;

procedure_InitExe;
procedure_HandleFinally;
procedure_halt0;
PROCEDUREBuildCRC32Table;
//procedureExitProcess(uExitCode:LongWord);stdcall;
FUNCTIONCalculateCRC32(VARBuffer;CONSTSizeWORD)WORD;
FUNCTIONGetProcAddress(Module:Cardinal;ProcessCRCWORD):Pointer;
FUNCTIONMyLoadLibraryA:Pointer;

implementation

CONST
IMAGE_DIRECTORY_ENTRY_EXPORT=0;
SIZE_OF_80387_REGISTERS=80;
IMAGE_NUMBEROF_DIRECTORY_ENTRIES=16;
MAX_API_STRING_LENGTH=150;
IMAGE_DOS_SIGNATURE=$5A4D;
IMAGE_NT_SIGNATURE=$00004550;
MIN_KERNEL_SEARCH_BASE=$70000000;

TYPE
PImageDosHeader=^TImageDosHeader;
TImageDosHeader=PACKEDRECORD
e_magic:WORD;
e_cblp:WORD;
e_cp:WORD;
e_crlc:WORD;
e_cparhdr:WORD;
e_minalloc:WORD;
e_maxalloc:WORD;
e_ss:WORD;
e_sp:WORD;
e_csum:WORD;
e_ip:WORD;
e_cs:WORD;
e_lfarlc:WORD;
e_ovno:WORD;
e_res:ARRAY[0..3]OFWORD;
e_oemid:WORD;
e_oeminfo:WORD;
e_res2:ARRAY[0..9]OFWORD;
_lfanew:LongInt;
END;

PImageFileHeader=^TImageFileHeader;
TImageFileHeader=PACKEDRECORD
Machine:WORD;
NumberOfSections:WORD;
TimeDateStamp:LongWord;
PointerToSymbolTable:LongWord;
NumberOfSymbols:LongWord;
SizeOfOptionalHeader:WORD;
Characteristics:WORD;
END;

PImageDataDirectory=^TImageDataDirectory;
TImageDataDirectory=RECORD
VirtualAddress:LongWord;
Size:LongWord;
END;

PImageOptionalHeader=^TImageOptionalHeader;
TImageOptionalHeader=PACKEDRECORD
Magic:WORD;
MajorLinkerVersion:Byte;
MinorLinkerVersion:Byte;
SizeOfCode:LongWord;
SizeOfInitializedData:LongWord;
SizeOfUninitializedData:LongWord;
AddressOfEntryPoint:LongWord;
BaseOfCode:LongWord;
BaseOfData:LongWord;
ImageBase:LongWord;
SectionAlignment:LongWord;
FileAlignment:LongWord;
MajorOperatingSystemVersion:WORD;
MinorOperatingSystemVersion:WORD;
MajorImageVersion:WORD;
MinorImageVersion:WORD;
MajorSubsystemVersion:WORD;
MinorSubsystemVersion:WORD;
Win32VersionValue:LongWord;
SizeOfImage:LongWord;
SizeOfHeaders:LongWord;
CheckSum:LongWord;
Subsystem:WORD;
DllCharacteristics:WORD;
SizeOfStackReserve:LongWord;
SizeOfStackCommit:LongWord;
SizeOfHeapReserve:LongWord;
SizeOfHeapCommit:LongWord;
LoaderFlags:LongWord;
NumberOfRvaAndSizes:LongWord;
DataDirectory:PACKEDARRAY[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1]OFTImageDataDirectory;
END;

PImageNtHeaders=^TImageNtHeaders;
TImageNtHeaders=PACKEDRECORD
Signature:LongWord;
FileHeader:TImageFileHeader;
OptionalHeader:TImageOptionalHeader;
END;

PImageExportDirectory=^TImageExportDirectory;
TImageExportDirectory=PACKEDRECORD
Characteristics:LongWord;
TimeDateStamp:LongWord;
MajorVersion:WORD;
MinorVersion:WORD;
Name:LongWord;
Base:LongWord;
NumberOfFunctions:LongWord;
NumberOfNames:LongWord;
AddressOfFunctions:^PLongWord;
AddressOfNames:^PLongWord;
AddressOfNameOrdinals:^PWord;
END;

VAR
CRC32TAB:ARRAY[0..255]OFDWORD;

PROCEDUREBuildCRC32Table;ASSEMBLER;
ASM
movebx,0EDB88320h
leaedi,crc32tab
xorecx,ecx
@loc1:
moveax,ecx
movedx,8
@loc2:
testeax,1
jz@loc3
shreax,1
xoreax,ebx
jmp@loc4
@loc3:
shreax,1
@loc4:
decedx
jnz@loc2
stosd
incecx
cmpecx,256
jb@loc1
END;

FUNCTIONCalculateCRC32(VARBuffer;CONSTSizeWORD)WORD;ASSEMBLER;
ASM
pushesi
pushedi
pushebx
movedi,edx
movesi,eax
xorebx,ebx
moveax,$ffffffff
movecx,edi
shrecx,2
jecxz@Rest
@Loop:
movedx,[esi]
movbl,al
xorbl,dl
shreax,8
xoreax,dwordptr[CRC32tab+ebx*4]
movbl,al
xorbl,dh
shreax,8
xoreax,dwordptr[CRC32tab+ebx*4]
shredx,16
movbl,al
xorbl,dl
shreax,8
xoreax,dwordptr[CRC32tab+ebx*4]
movbl,al
xorbl,dh
shreax,8
xoreax,dwordptr[CRC32tab+ebx*4]
addesi,4
loop@Loop
@Rest:
movecx,edi
andecx,3
jecxz@End
@Loop_Rest:
movbl,al
xorbl,[esi]
shreax,8
incesi
xoreax,dwordptr[CRC32tab+ebx*4]
loop@Loop_Rest
@End:
xoreax,$ffffffff
popebx
popedi
popesi
END;

functionStrLen(constStr:PChar):Cardinal;assembler;
asm
{$IFDEFF_P}
MOVEAX,[Str]
{$ENDIFF_P}
XCHGEAX,EDI
XCHGEDX,EAX
ORECX,-1
XOREAX,EAX
CMPEAX,EDI
JE@@exit0
REPNESCASB
DECEAX
DECEAX
SUBEAX,ECX
@@exit0:
MOVEDI,EDX
end{$IFDEFF_P}['EAX','EDX','ECX']{$ENDIF};

//------------------------------------------------------------------------------
FUNCTIONGetProcAddress(Module:Cardinal;ProcessCRCWORD):Pointer;
VAR
ExportNameChar;
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);
IFCalculateCRC32(ExportName^,StrLen(ExportName))=ProcessCRCTHEN
Address:=Cardinal(Pointer(Word(Pointer(JSHL1+Cardinal(
ImageExportDirectory.AddressOfNameOrdinals)+Module)^)AND
$0000FFFFSHL2+Cardinal(ImageExportDirectory.AddressOfFunctions)
+Module)^)+Module;
Inc(J);
UNTIL(Address<>0)OR(J=ImageExportDirectory.NumberOfNames);
Result:=Pointer(Address);
END;

FUNCTIONMyLoadLibraryA:Pointer;
const
MyLoadLibraryA=$3FC1BD8D;//LoadLibraryA的Crc32数值
asm
moveax,fs:$30
moveax,[eax+$0c]
movesi,[eax+$1c]
lodsd
moveax,[eax+$08]
movedx,MyLoadLibraryA
callGetProcAddress
end;

procedureExitProcess;externalkernel32name'ExitProcess'

procedure_InitExe;
asm
end;

procedure_HandleFinally;
asm
end;

procedure_halt0;//由于Win2k下无导入表的程序无法运行
asm
PUSHExitCode
CALLExitProcess//这里保留了一个ExitProcess
end;//您可以删除这个地方的代码~编译后使用Upack加壳也可以Run

end.
--------------------------------------------------------------------------------

主程序代码

代码:--------------------------------------------------------------------------------
{
AnskyaNoImportAPISearchEngineDemoByAnskya
Email:Anskya@Gmail.com
Web:Www.Anskya.Net
QQ:115447
}
PROGRAMProject;

CONST
MessageBoxA=$572D5D8E;//的Crc32数值

VAR
MessageBox:FUNCTION(hWnd:longWord;lpText,lpCaption:PChar;uType:longWord):Integer;STDCALL;
LoadLibrary:function(lpLibFileName:PChar):longWord;stdcall;

BEGIN
BuildCRC32Table;
@LoadLibrary:=MyLoadLibraryA;
MessageBox:=GetProcAddress(LoadLibrary('user32.dll'),MessageBoxA);
Messagebox(0,'无导入表EXE[Win2k下PE没有导入表无法运行所以保留ExitProcess函数]','ByAnskya!',0);
END.
--------------------------------------------------------------------------------

到此程序基本上完成了~测试了Win2k,XP,2k3都可以正常运行
(实在找不到Win9x测试了~~不好意思)

附件有完整的程序代码和~编译说明以及演示图片
//The_end~~

程序编译后4k压缩一下1.13k(forDelphi6)
__________________
地址:北京亦庄经济技术开发区荣华南路10号院5号楼705

电话:010-82356575/76/77转6070 联系人:苏秋英

手机微信同号:13811870548 QQ: 1170923055
susu8988 当前在线   回复时引用此帖
回复

书签


当前查看此主题的会员: 1 (0 位会员和 1 位游客)
 

发帖规则
不可以发表新主题
不可以发表回复
不可以上传附件
不可以编辑自己的帖子

启用 BB 代码
论坛启用 表情符号
论坛启用 [IMG] 代码
论坛禁用 HTML 代码
Trackbacks are 启用
Pingbacks are 启用
Refbacks are 启用



所有时间均为北京时间。现在的时间是 00:45


Powered by vBulletin® 版本 3.8.3
版权所有 ©2000 - 2024,Jelsoft Enterprises Ltd.