4

I have this code in assembly:

global _start
section .rodata
  hello: db "Hello World!", 10

section .text

_start:
    mov eax,4           
    mov ebx,1          
    mov ecx,hello       
    mov edx,13     
    int 80h             

    ; Terminate program
    mov eax,1          
    xor ebx,ebx           
    int 80h

If I take objdump of the following code, I get:

enter image description here

If I get NUL characters in the objdump I will not be able to achieve the task I'm working on. How can I get objdump without any NUL(0x00) bytes?

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
srccode
  • 721
  • 4
  • 16
  • 2
    The file you assembled (and have at the top of your question) is not the one you objdumped. – Michael Petch Mar 10 '19 at 13:59
  • 2
    I will assume that this is really all about shellcode exploits? – Michael Petch Mar 10 '19 at 14:00
  • 2
    You are looking at unrelated files. It isn't even a 64-bit-assemble/32-bit-disassemble mismatch, in your source you have `syscall` while in the disassembled you have `int 80` - they are completely unrelated files. – Matteo Italia Mar 10 '19 at 14:01
  • Sorry for the inconvenience. I have updated the code. – srccode Mar 10 '19 at 14:05
  • @MichaelPetch Yes, I'm trying buffer overflow attack – srccode Mar 10 '19 at 14:06
  • Please do not post pictures of text. Instead, copy paste the text in the image into your question. – fuz Mar 10 '19 at 14:12
  • 1
    I'd recommend looking at the shellcode in this Stackoverflow answer I wrote: https://stackoverflow.com/a/50690339/3857942 . It is 64-bit code that prints a string to the console and then exits and avoids NUL bytes which is pretty much exactly what you are trying to do here. – Michael Petch Mar 10 '19 at 14:12
  • Your title no longer matches the code. Are you trying to write 64-bit shellcode or 32-bit? 32-bit syscalls (via `int 0x80` using the stack will not work in a 64-bit exploit because the stack pointer can't be represented in 32-bits. You will need to use 64-bit syscalls in your exploit. Otherwise you will have to write shell code for 32-bit, assemble it as 32-bit and run it in a 32-bit program. Your objdump suggests you assembled with `-f elf64` and are targeting 64-bit. – Michael Petch Mar 10 '19 at 14:14
  • With 32-bit bit code you are going to have to consider looking at alternatives like the [JMP/CALL/POP method](https://marcosvalle.github.io/osce/2018/05/06/JMP-CALL-POP-technique.html) to avoid NUL bytes when trying to use the string. – Michael Petch Mar 10 '19 at 14:20
  • 2
    `objdump` is just a disassembler. **It only shows the bytes that are in the file.** Write asm that assembles to machine code doesn't contain any `00` bytes, then the `objdump` output will be free of them. The most obvious one is that you have to avoid `mov r32, imm32` for small constants, because there's unfortunately no `r/m32, imm8` form of `mov`. push imm8 / pop reg is a common workaround, or use `lea` from a known base. – Peter Cordes Mar 10 '19 at 14:41

1 Answers1

7

In order to eliminate NUL(0x00) bytes in OBJDUMP you need to write shellcode that assembles into instructions that don't include NUL bytes. The methods you use are also dependent on the target. Are you writing a 32-bit exploit or a 64-bit exploit? Your current question appears to be a 32-bit exploit, so I will make that assumption.

The more complex situation in 32-bit code is getting the address of a string (that will be stack based when run as an exploit without NUL bytes). You can use the JMP/CALL/POP method to achieve that. Alternatively You can also build the Hello World! string on the stack directly. I will propose a version using JMP/CALL/POP as described in the article:

hello1.asm:

global _start    
section .text

_start:
    jmp call
pop:
    pop ecx                     ; ECX = address of hello
    xor eax, eax                ; EAX = 0
    mov al, 4                   ; EAX = 4 (int 0x80 sys_write)
    xor ebx, ebx
    inc ebx                     ; EBX = 1 (1 = Standard output)
    xor edx, edx
    mov dl, hellolen            ; EDX = length of hello string
    int 0x80

    ; Terminate program
    xor eax, eax
    inc eax                     ; EAX = 1 (int 0x80 sys_exit)
    xor ebx, ebx                ; EBX = return value of 0
    int 0x80
call:
    call pop
    hello: db "Hello World!", 10
hellolen equ $-hello

You can assemble and link this code to a 32-bit executable called hello1 using:

nasm -f elf32 hello1.asm -o hello1.o
ld -melf_i386 hello1.o -o hello1

The result of objdump -D hello1 is:

hello1:    file format elf32-i386  

Disassembly of section .text:

08048060 <_start>:
 8048060:       eb 15                   jmp    8048077 <call>

08048062 <pop>:
 8048062:       59                      pop    %ecx
 8048063:       31 c0                   xor    %eax,%eax
 8048065:       b0 04                   mov    $0x4,%al
 8048067:       31 db                   xor    %ebx,%ebx
 8048069:       43                      inc    %ebx
 804806a:       31 d2                   xor    %edx,%edx
 804806c:       b2 0d                   mov    $0xd,%dl
 804806e:       cd 80                   int    $0x80
 8048070:       31 c0                   xor    %eax,%eax
 8048072:       40                      inc    %eax
 8048073:       31 db                   xor    %ebx,%ebx
 8048075:       cd 80                   int    $0x80

08048077 <call>:
 8048077:       e8 e6 ff ff ff          call   8048062 <pop>

0804807c <hello>:
 804807c:       48                      dec    %eax
 804807d:       65 6c                   gs insb (%dx),%es:(%edi)
 804807f:       6c                      insb   (%dx),%es:(%edi)
 8048080:       6f                      outsl  %ds:(%esi),(%dx)
 8048081:       20 57 6f                and    %dl,0x6f(%edi)
 8048084:       72 6c                   jb     80480f2 <hello+0x76>
 8048086:       64 21 0a                and    %ecx,%fs:(%edx)

You should note that there are no NUL bytes with this code. If you run ./hello1 as a standalone program it should output:

Hello World!

You can now convert this to a shellcode string with:

objcopy -Obinary hello1 shellcode.bin
hexdump -v -e '"\\""x" 1/1 "%02x" ""' shellcode.bin

The OBJCOPY command converts the executable to raw binary and the second outputs a string that can be used for the purposes of an exploit. The output should be:

\xeb\x15\x59\x31\xc0\xb0\x04\x31\xdb\x43\x31\xd2\xb2\x0d\xcd\x80\x31\xc0\x40\x31\xdb\xcd\x80\xe8\xe6\xff\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x0a

If you are looking for the equivalent code for 64-bit exploits you can find such an example in this Stackoverflow answer.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • Hi, thank you for taking your time to answer this. But there is a small problem in the shellcode generated. It has \xeb\x15\x59\x31\xc0\xb0\x04 and that's copy stops (\x04). Is there any work around for the same?. – srccode Mar 10 '19 at 17:27
  • 3
    One possible solution (haven't tested it) is, for example, to replace `mov $0x4,%al` with `mov $69,%al ; sub $65,%al`. This would create `E` and `A` characters. – zx485 Mar 10 '19 at 17:56
  • Also, inc eax is not setting eax value to 1. I connected gdb and checked and it shows eax=-4 after the increment. As inc command is not working as expected, it results in non termination of the program. – srccode Mar 10 '19 at 18:44
  • 1
    @srccode You are doing something wrong that is outside the scope of this actual question. Your issues now seem to revolve around running the code as an exploit.I recommend starting an entirely new question with your shellcode from this question, the code of the program you are trying to exploit and all the command you use to assemble/link/build and run so that someone can attempt to identify/reproduce your problem – Michael Petch Mar 10 '19 at 18:47
  • inc al increments the value of al properly bu inc eax or inc ebx doesn't work. – srccode Mar 10 '19 at 18:50