2011-10-28 12 views
8

Linux'u x86 ile kullanıyorum (tam olarak 64 bit). Mevcut talimatın adresini almanın bir yolu var mı? Aslında, setjmp/longjmp'un kendi basitleştirilmiş sürümlerini yazmak istiyorum. Here, R .. longjmp'un basitleştirilmiş bir sürümünü yayınladı. setjmp'un nasıl uygulandığı hakkında herhangi bir fikir. İstisnalar ve sinyaller vb. Hesaba katılmadan basitleştirilmiş bir versiyon ...x86 için geçerli talimatın adresini al

cevap

24

64-bit kodlara inanıyorum ki sadece lea rax, [rip].

32 bit deyim geçerli:

 call next 
next: pop eax 
+0

kullanabilirsiniz Ve 32 bit böyle bir şey yapmak mümkün mü? – MetallicPriest

+1

@MetallicPriest: Yanıt güncellendi. – NPE

+0

Serin hüner hun :-p! – MetallicPriest

0

This sitesi aşağıdaki gibidir setjmp ve longjmp basit versiyonunu verir.

#include "setjmp.h" 

#define OFS_EBP 0 
#define OFS_EBX 4 
#define OFS_EDI 8 
#define OFS_ESI 12 
#define OFS_ESP 16 
#define OFS_EIP 20 

__declspec(naked) int setjmp(jmp_buf env) 
{ 
    __asm 
    { 
    mov edx, 4[esp]   // Get jmp_buf pointer 
    mov eax, [esp]   // Save EIP 
    mov OFS_EIP[edx], eax 
    mov OFS_EBP[edx], ebp // Save EBP, EBX, EDI, ESI, and ESP 
    mov OFS_EBX[edx], ebx 
    mov OFS_EDI[edx], edi 
    mov OFS_ESI[edx], esi 
    mov OFS_ESP[edx], esp 
    xor eax, eax    // Return 0 
    ret 
    } 
} 

__declspec(naked) void longjmp(jmp_buf env, int value) 
{ 
    __asm 
    { 
    mov edx, 4[esp]   // Get jmp_buf pointer 
    mov eax, 8[esp]   // Get return value (eax) 

    mov esp, OFS_ESP[edx] // Switch to new stack position 
    mov ebx, OFS_EIP[edx] // Get new EIP value and set as return address 
    mov [esp], ebx 

    mov ebp, OFS_EBP[edx] // Restore EBP, EBX, EDI, and ESI 
    mov ebx, OFS_EBX[edx] 
    mov edi, OFS_EDI[edx] 
    mov esi, OFS_ESI[edx] 

    ret 
    } 
} 
+3

Bu, sorunuzun cevabı olan @MetallicPriest? – karlphillip

+0

Gerekirse, cevabınızı, eğer iyi ise: -p! – MetallicPriest

4

ofset içine-akım kademeli yazmacı (EIP), normal olarak erişilemez. Bununla birlikte, dolaylı olarak okumak için hack-yolu var - programı EIP'nin değerini yığının üzerine itmek için kandırırsınız, sonra sadece okuyun. Eğer bir CALL FAR talimat, bölüm değerini (CS) kullanırsanız hem yığına edilecektir

call NextLine 
NextLine: 
    pop eax    ; address of previous line stored in EAX 

:

GetAddress: 
    mov eax, [esp] 
    ret 
... 
    call GetAddress  ; address of this line stored in eax 

Veya daha da basit: Bu gibi görünen bir alt yordam oluşturabilir .


Eğer C kullanarak ediyorsanız, this page üzerinde kullanabilirsiniz çeşitli derleyici özgü C-uzantıları vardır. Ayrıca bkz. this interesting article.

+0

OP, ilgili adrese sahip x86_64 sorusunu sorar, bu yüzden RIP için "erişilebilir" yönergeleri var –

8

GCC kullanarak, ayrıca __builtin_return_address

+2

Amaçlanan etkiyi elde etmek için bunu bir işlevde sarmanız gerekeceğini unutmayın, aksi halde Mevcut komutun adresi yerine geçerli yığın çerçevesi için dönüş adresi. – Jason

+2

eğer GCC kullanıyorsanız daha kolay kullanılır ['somelabel: return && somelabel;'] (http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html) –

+1

@Jason haklı ve aynı zamanda __builtin_return_address öğesini içeren sarma işlevinin tanımı bir başlık dosyasında değildir ve hiçbir zaman satır içi olmayacaktır. –

İlgili konular