Reputation: 635
I want to be able to convert a single line of ASM into shellcode. I.E:
CALL EBX
How do I go about doing this, and also being able to properly convert this shellcode so that I can store it in a variable in a delphi application. I.E:
var ShellCodeArray: array[0..3] of Byte = ($55,$8B,$EC,$81);
Upvotes: 5
Views: 1744
Reputation: 7340
Just use a dummy procedure following the code and substract the two, eg:
procedure Code
asm
call ebx;
end;
procedure CodeEnd;
asm end;
CodeSize := DWORD_PTR(@CodeEnd) - DWORD_PTR(@Code);
CopyMemory(@MyByteArray[0], @Code, CodeSize);
Note that in code you use also use Delphi code instead of asm as long as you don't call into other code (functions/procedures/rtl)
EDIT: as an answer to the comments from Serg and David Heffernan I verified the results with Delphi 2010 in release mode.
I used the following code:
procedure Code;
asm
mov eax, 0;
end;
procedure CodeEnd;
asm end;
procedure TForm4.Button1Click(Sender: TObject);
begin
ShowMessageFmt('CodeSize=%d', [DWORD_PTR(@CodeEnd) - DWORD_PTR(@Code)]);
end;
The reported CodeSize is 8 Bytes, I then verified using Ida Pro (disassembler on the executable):
.text:004B3344 Code proc near
.text:004B3344
.text:004B3344 B8 00 00 00 00 mov eax, 0
.text:004B3349 C3 retn
.text:004B3349 Code endp
.text:004B3349
.text:004B3349 ; -----------------------------
.text:004B334A 8B C0 align 4
So in this example mov eax, 0 is 5 bytes (B8 00 00 00 00), retn (added by compiler) is 1 byte (C3), align 4 is 2 bytes (8B C0) which is 8 in total.
Upvotes: 1
Reputation: 613013
For what it's worth, I'd avoid the duplication of Serg's answer and write it like this:
function CodeToBytes: TBytes;
var
StartAddr, EndAddr: Pointer;
begin
asm
LEA EAX, @@start
MOV StartAddr, EAX
LEA EAX, @@end
MOV EndAddr, EAX
JMP @@end
@@start:
CALL EBX
@@end:
end;
SetLength(Result, Integer(EndAddr)-Integer(StartAddr));
Move(StartAddr^, Pointer(Result)^, Length(Result));
end;
Obviously you can stick whatever you like in between the start and end labels.
Upvotes: 2
Reputation: 27493
If I get you right, you want to obtain a machine code of a single assembler instruction CALL EBX
using Delphi built-in assembler.
function CodeSize: Integer;
asm
lea EAX, @@end
lea EDX, @@start
sub EAX, EDX
JMP @@end
@@start:
call EBX
@@end:
end;
procedure Code;
asm
call EBX
end;
function CodeToBytes: TBytes;
var
I, N: Integer;
P: PByte;
begin
N:= CodeSize;
SetLength(Result, N);
P:= @Code;
for I:= 0 to N - 1 do begin
Result[I]:= P^;
Inc(P);
end;
end;
Upvotes: 5