Delphi程序增加破解难度
来源:来自网络 作者:不详 日期:2010-09-15 热度:给Window API 加个HOOK,增加分析难度
在软件加密过程中,很有可能要用到API函数,而且对API的返回结果,API的调用位置等相对比较敏感
我们有必要给API增加一点分析难度,先转一圈再去调用这个API,调用完后在转一圈才回去,顺便加点小花,
增加分析难度
我们该如果作呢,
一、THookClass(网上有源代码)写一个API HOOK的程序
钩住API后,想怎么溜达就怎么溜达,溜达够了才返回,分析者分析时会花大量时间来跟着你溜达
二、用以下函数ChangeAPIHead处理API
原理: 首先申请一段内存,然后复制一段程序到新内存中,让API HOOK到这个新内存地址,然后新
内存地址的代码里完成还原API,调用API,再HOOK API的动作,然后返回,加些小花
ChangeAPIHeadUnit.pas
//**************************CHANGE API HEAD CODE******************************//
//Author : 蓝色光芒 //
//2005-12-22 last update at www.1284.net //
unit ChangeAPIHeadUnit;
interface
Uses
Windows , Messages;
//API Function must be stdcall;
Function ChangeAPIHead(APIFunAddress : Pointer) : Integer;stdcall;
implementation
Type
THeadCode = array [0..4] of Char;
PHeadCode = ^THeadCode;
TNewProcBuf = array [0..199] of Char;
TAPIHead = packed Record
NewProcBuf : TNewProcBuf; //新程序的代码区域
OldHead : THeadCode;
FunAddress : Pointer;
NewHead : THeadCode;
WriteMemoProc : Pointer;
APIResult : DWORD;
end;
PAPIHead = ^TAPIHead;
Const
HeadCodeSize = SizeOf(THeadCode);
CopyCodeSize = SizeOf(TNewProcBuf);
APIResultOffset = CopyCodeSize + HeadCodeSize + 4 + HeadCodeSize + 4;
MaxAPIParamCount = 16;
var
Handle : THandle;
function FinalFunctionAddress(Code: Pointer): Pointer;
begin
Result := Code;
if Code<>NIL then begin
if PWORD(Code)^ = $25FF then
Result := PPointer(PPointer(Pointer(DWORD(Code)+2))^)^;
end;
end;
procedure NewAPIProcedure;stdcall;
asm
CALL @GetCurrentEIP;
DB $E9; //花指令
@GetCurrentEIP:
MOV EAX , [ESP];
ADD ESP , 4;
SUB EAX , 5;
PUSH EAX; //程序的入口地址,也就是PAPIHead的地址
PUSH 0;
PUSH ESP; //*ESP ->> lpNumberOfBytesWritten
PUSH HeadCodeSize; //nSize
ADD EAX , CopyCodeSize;
PUSH EAX; //APIHead^.OldCode ->> lpBuffer
ADD EAX , HeadCodeSize;
PUSH [EAX]; //APIHead^.FunAddress ->> lpBaseAddress
PUSH Handle;
ADD EAX , HeadCodeSize + 4; //WriteProcessMemory的地址
CALL [EAX]; //Call WriteProcessMemory; 还原被修改API头
ADD ESP , 4;
POP EAX;
PUSH EAX;
ADD EAX , CopyCodeSize + HeadCodeSize; //APIHead^.FunAddress ->> EAX
PUSH EBP;
MOV EBP , ESP;
SUB ESP , MaxAPIParamCount * 4;
MOV ECX , 0;
@LOOP:
MOV EDX , [ESP + (MaxAPIParamCount+3) * 4 + ECX * 4];
MOV [ESP + ECX * 4] , EDX;
INC ECX;
CMP ECX , 15;
JNZ @LOOP;
CALL @CALLAPIReturnHere;
@CALLAPIReturnHere:
ADD [ESP] , 7; //Return To >> JMP [EAX]后面一句->MOV EDX , EBP;
JMP [EAX]; //CALL API Function
DB $E9; //花指令头
MOV EDX , EBP; // \
SUB EDX , ESP; // |
SUB EDX , MaxAPIParamCount*4; // |
MOV ESP , EBP; // |
POP EBP; // |
POP ECX; //程序入口地址 // |效验API参数,然后平衡栈
MOV [ECX + APIResultOffset] , EAX; //保存API返回值 // |
MOV EAX , ECX; // |
MOV ECX , [ESP]; //本过程执行完后的返回地址 // |
SUB ESP , EDX; // |
MOV [ESP],ECX; // /
PUSH EAX; //本程序的入口地址保护
PUSH 0;
PUSH ESP; //lpNumberOfBytesWritten
PUSH HeadCodeSize; //nSize
ADD EAX , CopyCodeSize + HeadCodeSize + 4;
PUSH EAX; //APIHead^.NewCode ->> lpBuffer
SUB EAX , 4;
PUSH [EAX]; //APIHead^.FunAddress ->> lpBaseAddress
PUSH Handle;
ADD EAX , HeadCodeSize + 4; //WriteProcessMemory的地址
CALL @CALLAPIReturnHere2;
@CALLAPIReturnHere2:
ADD [ESP] , 7; //Return To >> JMP [EAX]后面一句->ADD ESP , 4;
JMP [EAX]; //CALL WriteProcessMemory
DB $E9; //花指令头
ADD ESP , 4;
POP EAX;
MOV EAX , [EAX + APIResultOffset]; //取出API返回值
ADD ESP , 4;
JMP [ESP-4]; //返回
end;
Function ChangeAPIHead(APIFunAddress : Pointer) : Integer;stdcall;
var
APIHead : PAPIHead;
OldAddress : Pointer;
begin
Result := NO_ERROR;
OldAddress := FinalFunctionAddress(APIFunAddress);
if Handle=0 then Handle := OpenProcess(PROCESS_ALL_ACCESS,FALSE, GetCurrentProcessID());
if Handle = 0 then exit;
New(APIHead);
FillChar(APIHead^,SizeOf(TAPIHead),$90);
APIHead^.FunAddress := OldAddress;
APIHead^.OldHead := PHeadCode(OldAddress)^;
PByte(@APIHead^.NewHead[0])^ := $E9;
PDWORD(@APIHead^.NewHead[1])^ := DWORD(APIHead) - DWORD(OldAddress) - 5;
CopyMemory(@APIHead.NewProcBuf,@NewAPIProcedure,CopyCodeSize);
APIHead.WriteMemoProc := @WriteProcessMemory;
OldAddress := NIL;
WriteProcessMemory(Handle,
APIHead^.FunAddress,
@APIHead^.NewHead,
HeadCodeSize,
PDWORD(@OldAddress)^);
end;
end.
首先保存以上单元内容,并引用本单元,然后在你的程序的某处这样调用
ChangeAPIHead(@APIFunName); 如:
ChangeAPIHead(@MessageBox);
执行以上这句之后,MessageBox这个函数已经被作过处理了,跟踪这个函数时会麻烦一些了
也可以对同对一个函数作多次处理,效果更好




![还你真实的开幕式!震撼美图[转]【连载】](/up_files/image/Article/2008/08/12/57015031.jpg)



