2012-11-07 37 views
5

我希望能夠將一行ASM轉換爲shellcode。即:如何獲得編譯時已知的彙編指令的機器碼?

CALL EBX 

我如何去這樣做,也能夠正確執行這種轉換的shellcode,這樣我可以將其存儲在一個Delphi應用程序中的變量。即:

var ShellCodeArray: array[0..3] of Byte = ($55,$8B,$EC,$81); 
+2

如果您使用帶有內置彙編程序的語言,爲什麼不使用該彙編程序? – hvd

+0

各種原因。但是,謝謝你的回覆。 –

+1

尋找類似的東西? http://www.delphibasics.info/home/delphibasicssnippets/executingpreparedshellcodeindelphi – bummi

回答

5

如果我得到你的權利,你要獲得使用單一的彙編指令CALL EBX的機器代碼德爾福內置彙編。

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; 
+0

你應該寫這個,以便只有一個asm塊的實例 –

+0

@DavidHeffernan - 爲什麼? – kludg

+0

總是比寫兩遍更好。也很容易做到。 –

1

對於它的價值,我會避免SERG的答案的重複,並把它寫這樣的:

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; 

很明顯,你可以堅持無論你的起點和終點標誌之間非常相似。

1

只需使用一個虛擬的過程完成之後的代碼,並在。減去二,如:

procedure Code 
asm 
    call ebx; 
end; 

procedure CodeEnd; 
asm end; 

CodeSize := DWORD_PTR(@CodeEnd) - DWORD_PTR(@Code); 
CopyMemory(@MyByteArray[0], @Code, CodeSize); 

注意,在代碼中你使用也使用Delphi代碼,而不是ASM只要你不叫成其他代碼(函數/程序/ rtl)

編輯:作爲對Serg和David Heffernan的評論的回答,我使用Delphi 2010在發佈模式下驗證了結果。

我用下面的代碼:

.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 

所以在這個例子MOV EAX:

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; 

報告CodeSize爲8個字節,我然後使用(在可執行拆裝)井田臨驗證,0是5個字節(B8 00 00 00 00),retn(由編譯器添加)是1個字節(C3),對齊4是2個字節(8B C0),總共是8個字節。

+0

不確定這是否安全,因爲編譯器可以對齊啞元過程的起始點,這就是我使用'CodeSize'函數的原因。 – kludg

+0

@Serg:如果它確實對齊(編譯器是否這樣做?我從來沒有見過這種情況),我當然希望編譯器插入NOP的:-) – Remko

+0

嗯nop的是好的,但即使它是隨機字節它應該無關緊要,因爲過程代碼以retn結尾 – Remko