概述
begin
Result := 'abc';
end;
00453BF5 C3 ret //返回
00453BF6 0000 //实际上是没用.作用是对齐代码
00453BF8 61626300 字符串abc
Function FixPChar(Value : PChar):PChar;forward;
Function A():PChar;
begin
Result := FixPChar('abc');
end;
Function FixPChar(Value : PChar):PChar; register;//register;加不加都无所谓.默认就是register;
asm
call @next //
@next: pop ecx //ecx里面装的就是@next的相对地址,当前执行时
mov ebx, offset @next //ebx里面装的就是@next的绝对地址,编译时生成的
add eax, ecx //返回Value的地址+(相对地址-绝对地址)
sub eax, ebx
end;
procedure _end();
begin
end;
现在我们可以把A函数和FixChar拷贝到任何地方使用了.如何拷贝呢?
我们只要拷贝A函数的地址为起始,_end函数的地址为终点的数据块就可以用了.
例如
Type
TFunc = Function():PChar;
var
M : String;
begin
//
SetLength(M, Integer(@_end) - Integer(@A)); //为M分配长度
CopyMemory(PChar(M), @A, Length(M)); //把A函数和_end之间的代码拷贝到M
ShowMessage(TFunc(PChar(M))()); //把M强制转换为TFunc类型执行
end;
网上流传很广的一个API搜索就是用CRC来避开字符串的.如果用这样的技术完全可以省略计算CRC的步骤.
原函数如下: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;
改良后如下:
function FixPChar(Value: PChar): PChar; forward;
function strcmp(p1, p2: PChar): boolean; forward;
function GetProcAddress(Module: Cardinal; ProcessName: PChar): 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 strcmp(ExportName, ProcessName) 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;
function strcmp(p1, p2: PChar): boolean;
begin
Result := False;
while (p1^ = p2^) do
begin
if (P1^ = #0) or (P2^ = #0) then
begin
Result := True;
Exit;
end;
Inc(P1);
Inc(P2);
end;
end;
function FixPChar(Value: PChar): PChar; register; //register;加不加都无所谓.默认就是register;
asm
call @next //
@next: pop ecx //ecx里面装的就是@next的相对地址,当前执行时
mov ebx, offset @next //ebx里面装的就是@next的绝对地址,编译时生成的
add eax, ecx //返回Value的地址+(相对地址-绝对地址)
sub eax, ebx
end;
procedure _end();
begin
end;
调用的时候直接 GetProcAddress(hm,FixPChar('函数名'));就可以了.免了事先计算函数名CRC的麻烦.
最后
以上就是大力睫毛为你收集整理的Delphi是最适合编写ShellCode的工具的全部内容,希望文章能够帮你解决Delphi是最适合编写ShellCode的工具所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复