2014-07-10 91 views
1

我想寫一個程序集,一旦加載到內存中,寫入新的指令,但我不是100%確定如何繼續,因爲我有對指令指針和其他裝配概念有些懷疑。我假設的方法:在x86彙編中實現反射(在運行時編輯程序)

_func: 

    push rip ; Not allowed to push RIP, how can I read from RIP? 
    jmp stage1 

    stage2: 

    mov eax, 0 
    ret 

    stage1: 

    pop rbx 

    ; How many times should I increment rbx to point to ‘mov eax, 0’? 
    ; Assuming this is done: 

    ;Move opcodes for ‘mov eax, 1’ into memory where ‘mov eax, 0’ located 

    mov [rbx], 0xB8 
    mov [rbx+1], 0x01 
    mov [rbx+2], 0x00 
    mov [rbx+3], 0x00 
    mov [rbx+4], 0x00 

    jmp stage2 

當跳轉到第2階段,而不是 'MOV EAX,0',它會遇到操作碼 'B8 01 00 00 00',並解釋 'MOV EAX,1。'我的一般方法是否正確,並且有人能夠填補代碼中的空白嗎?


附加混亂/問題

是否RBX指向的指令線,或「整體」行的第一個字節?是上述方法正確,或者我應該寫:

mov [rbx], B801000000h 

操作系統:的Mac OS X 10.9 彙編: NASM

+0

我不會把這種「反思」 - 這個詞是有點高層次的概念。自修改代碼更像它。 http://stackoverflow.com/questions/24676966/implementing-reflection-in-x86-assembly-editing-the-program-whilst-running –

回答

1

在16位 「實模式」 這樣做很簡單。當我開始組裝編程時,我使用反射實現了一個循環。

然而下16位或32位的「受保護模式」或在「長模式」(64位),這是比較麻煩:

在這些模式中存儲器可防覆蓋保護。由於「Pentium Pro」處理器,也可以保護內存不被執行。

Windows和Linux都使用這些功能,因此默認情況下,可修改的內存不能包含可執行代碼,並且包含可執行代碼的內存不能被覆蓋。

您必須分配既可寫又可執行的內存(或更改現有內存的內存訪問)。請參閱Windows中的「VirtualAlloc」和「VirtualProtect」功能或Linux中的「mmap」和「mprotect」。然後你必須將代碼移到那塊內存中。

順便說一句:下面的命令是錯誤的:

jmp stage1 

它必須是「打電話」,而不是在堆棧上「JMP」,因爲「JMP」不「推」的返回地址。

+0

在Mac OS X上,什麼是VirtualAlloc等價的功能? – user45389

+0

據我所知,Mac OS X與Linux相似,所以它應該(我不確定!)也是「mmap」。但是我知道iOS不允許可寫和可執行的內存。也許Mac OS X不允許。在這種情況下,反射是不可能的。 –

+0

如果我在內核特權級別運行代碼,即ring 0,我是否可以繞過使用mmap? – user45389

1

在16位「實模式」:

mov bx, stage2  ; NASM get offset address 

mov cs:[bx], 0xB8 
mov cs:[bx+1], 0x01 
mov cs:[bx+2], 0x00 
mov cs:[bx+3], 0x00 
mov cs:[bx+4], 0x00