Estou tentando entender a instrução jmp curta. Eu tenho um programa muito simples, compilado com nasm:
SECTION .data
bsh: db "/bin/sh",0
arr: dq bsh,0
SECTION .text
global main
main:
jmp short 0x20
mov edx, 0
mov rsi, arr
mov rdi, bsh
mov rax, 0x3b
syscall
mov ebx, 0
mov eax, 0x3c
syscall
Desmontado, o código fica assim em gdb (desmontar main):
0x00000000004000b0 <+0>: jmp 0x4000d1 <main+33>
0x00000000004000b2 <+2>: mov $0x0,%edx
0x00000000004000b7 <+7>: movabs $0x6000e8,%rsi
0x00000000004000c1 <+17>: movabs $0x6000e0,%rdi
0x00000000004000cb <+27>: mov $0x3b,%eax
0x00000000004000d0 <+32>: syscall
0x00000000004000d2 <+34>: mov $0x0,%ebx
0x00000000004000d7 <+39>: mov $0x3c,%eax
0x00000000004000dc <+44>: syscall
Estou tentando pular para 0x4000d2
. 34-2 = 32 = 0x20. 0x4000d2 - 0x4000b2 = 0x20. Não importa o que eu monte, o nasm sempre parece codificar o endereço de salto como um deslocamento de um byte após o início da instrução de salto. Porque é jmp short 0x20
montagem errado? (sem contar que jmp 0x20
teve um resultado diferente e foi uma instrução de 5 bytes em vez de uma instrução de 2 bytes)
Eu também estou lendo sobre quebrando a pilha por diversão e lucro. Aleph1 quer pular de jmp para ligar e depois de chamar para popl. Este é o código que ele usa:
jmp 0x26 # 2 bytes
popl %esi # 1 byte
movl %esi,0x8(%esi) # 3 bytes
movb $0x0,0x7(%esi) # 4 bytes
movl $0x0,0xc(%esi) # 7 bytes
movl $0xb,%eax # 5 bytes
movl %esi,%ebx # 2 bytes
leal 0x8(%esi),%ecx # 3 bytes
leal 0xc(%esi),%edx # 3 bytes
int $0x80 # 2 bytes
movl $0x1, %eax # 5 bytes
movl $0x0, %ebx # 5 bytes
int $0x80 # 2 bytes
call -0x2b # 5 bytes
.string "/bin/sh" # 8 bytes
Adicionando os bytes de popl %esi
para call -0x2b
Recebo 42. Não deveria a primeira instrução ser jmp 0x2a
? E subtraindo bytes do final da instrução de chamada até o início de popl %esi
Eu recebo -47. A chamada não deve ser call -0x2f
? Quando ele realmente cria um arquivo c e coloca sua montagem em um __asm__
bloco, ele usa as compensações que eu calculei, mas não neste código que é anterior a isso. O que mudou?
E enquanto estou aqui, ele não conseguiu acessar o eip e usá-lo para obter o deslocamento relativo da string na memória?
Respostas:
1 para resposta № 1Com a sintaxe da Intel, deve ser:
jmp short $+022h ;jump from current location ($ == 4000b0) to 4000d2
Observe que um salto em distância usando os mesmos $ + 022hA sintaxe ainda acabaria saltando para 4000d2, pois o montador geraria um campo de deslocamento menor. Esse tipo de uso é raro, com a exceção mais comum: jmp short $ + 2 usado no código legado para gerar atrasos muito curtos entre os acessos ao dispositivo de E / S.