2012-11-07 22 views
5

Tôi muốn có thể chuyển đổi một dòng ASM thành shellcode. I.E:Làm cách nào để lấy mã máy của lệnh lắp ráp được biết đến tại thời gian biên dịch?

CALL EBX 

Làm cách nào để thực hiện việc này và cũng có thể chuyển đổi đúng shellcode này để tôi có thể lưu trữ trong biến trong ứng dụng delphi. I.E:

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

Nếu bạn đang sử dụng một ngôn ngữ có trình tích hợp sẵn, tại sao không sử dụng bộ kết hợp đó? – hvd

+0

Lý do khác nhau. Nhưng cảm ơn bạn đã trả lời. –

+1

tìm kiếm nội dung như vậy? http://www.delphibasics.info/home/delphibasicssnippets/executingpreparedshellcodeindelphi – bummi

Trả lời

5

Nếu tôi yêu cầu bạn đúng, bạn muốn lấy mã máy của một hướng dẫn lắp ráp đơn CALL EBX sử dụng bộ ghép tích hợp Delphi.

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

Bạn nên viết điều này để chỉ có một thể hiện của khối asm –

+0

@DavidHeffernan - Tại sao? – kludg

+0

Luôn viết tốt hơn một lần thay vì hai lần. Rất dễ làm. –

1

Đối với những gì nó có giá trị, tôi muốn tránh sự trùng lặp của câu trả lời SERG và viết nó như thế này:

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; 

Rõ ràng bạn có thể dính vào bất cứ điều gì bạn muốn ở giữa đầu và cuối nhãn.

1

Chỉ cần sử dụng một thủ tục giả sau mã và trừ hai, ví dụ:

procedure Code 
asm 
    call ebx; 
end; 

procedure CodeEnd; 
asm end; 

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

Lưu ý rằng trong mã bạn cũng sử dụng sử dụng Delphi mã thay vì asm miễn là bạn đừng gọi vào mã khác (chức năng/thủ tục/rtl)

EDIT: như một câu trả lời cho các ý kiến ​​từ Serg và David Heffernan tôi đã xác minh kết quả với Delphi 2010 trong chế độ phát hành.

tôi đã sử dụng đoạn mã sau:

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; 

Các báo cáo CodeSize là 8 Bytes, tôi sau đó xác nhận bằng Ida Pro (disassembler trên thực thi):

.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 

Vì vậy, trong ví dụ này mov eax , 0 là 5 byte (B8 00 00 00 00), retn (được thêm bởi trình biên dịch) là 1 byte (C3), căn chỉnh 4 là 2 byte (8B C0) là 8 trong tổng số.

+0

Không chắc chắn là an toàn vì trình biên dịch có thể căn chỉnh điểm bắt đầu của thủ tục giả, đó là lý do tại sao tôi sử dụng chức năng 'CodeSize'. – kludg

+0

@Serg: Nếu nó liên kết (trình biên dịch có làm điều đó không? Tôi chưa bao giờ thấy điều đó) hơn tôi chắc chắn hopethe trình biên dịch chèn NOP :-) – Remko

+0

Vâng nop là ok nhưng ngay cả khi nó là ngẫu nhiên byte nó không nên quan trọng bởi vì mã thủ tục kết thúc bằng một retn – Remko

Các vấn đề liên quan