Question

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);
Was it helpful?

Solution

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;

OTHER TIPS

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top