Skip to content

Commit 1c171b4

Browse files
author
devseed
committed
adjust code format
1 parent b620e52 commit 1c171b4

3 files changed

Lines changed: 183 additions & 181 deletions

File tree

src/memdll/win_injectmemdll.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
2-
a tool to attach a dll inside a pe file
3-
v0.3.2, developed by devseed
2+
A tool to attach a dll inside a pe file
3+
v0.3.2, developed by devseed
44
5-
history:
5+
history:
66
see win_injectmemdll_shellcodestub.py
77
*/
88

Lines changed: 179 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -1,195 +1,197 @@
11
"""
2-
this file is for automaticly generate some shellcodes stub informations
3-
v0.3.2, developed by devseed
4-
5-
history:
6-
v0.1, initial version
7-
v0.2, add more function for shellcode
8-
v0.3, x86 and x64 no need to use exe's LoadLibraryA
9-
v0.3.1, fix x64 attach dll crash by align stack with 0x10
10-
v0.3.2, add support for ordinal iat and tls
2+
this file is for automaticly generate some shellcodes stub informations
3+
v0.3.2, developed by devseed
114
"""
125
import re
136
import sys
147
import lief
158
from keystone import Ks, KS_ARCH_X86, KS_MODE_32, KS_MODE_64
169

1710
def gen_oepinit_code32():
18-
ks = Ks(KS_ARCH_X86, KS_MODE_32)
19-
code_str = f"""
20-
// for relative address, get the base of addr
21-
call geteip;
22-
lea ebx, [eax-5];
23-
24-
// get loadlibrarya, getprocaddress
25-
call [ebx + findloadlibrarya];
26-
mov [ebx + findloadlibrarya], eax;
27-
call [ebx + findgetprocaddress];
28-
mov [ebx + findgetprocaddress], eax;
29-
30-
// bind iat
31-
push [ebx + findgetprocaddress]; // arg3, getprocaddress
32-
push [ebx + findloadlibrarya]; // arg2, loadlibraryas
33-
push [ebx + dllbase]; // arg1, dllbase value
34-
call [ebx + membindiat];
35-
add esp, 0xc;
36-
37-
// bind tls
38-
xor edx, edx;
39-
inc edx; // arg2, reason for tls
40-
push edx;
41-
push [ebx + dllbase] // arg1, dllbase
42-
call [ebx + membindtls]
43-
add esp, 0x8;
44-
45-
// call dll oep, for dll entry
46-
xor eax, eax;
47-
push eax; // lpvReserved
48-
inc eax;
49-
push eax; // fdwReason, DLL_PROCESS_ATTACH
50-
push [ebx + dllbase]; // hinstDLL
51-
call [ebx+dlloepva];
52-
53-
// jmp to origin oep
54-
jmp [ebx+exeoepva];
55-
56-
geteip:
57-
mov eax, [esp]
58-
ret
59-
60-
exeoepva: nop;nop;nop;nop;
61-
dllbase: nop;nop;nop;nop;
62-
dlloepva: nop;nop;nop;nop;
63-
memreloc: nop;nop;nop;nop;
64-
membindiat: nop;nop;nop;nop;
65-
membindtls: nop;nop;nop;nop;
66-
findloadlibrarya: nop;nop;nop;nop;
67-
findgetprocaddress: nop;nop;nop;nop;
68-
"""
69-
print("gen_oepinit_code32", code_str)
70-
payload, _ = ks.asm(code_str)
71-
print("payload: ", [hex(x) for x in payload])
72-
return payload
11+
ks = Ks(KS_ARCH_X86, KS_MODE_32)
12+
code_str = f"""
13+
// for relative address, get the base of addr
14+
call geteip;
15+
lea ebx, [eax-5];
16+
17+
// get loadlibrarya, getprocaddress
18+
call [ebx + findloadlibrarya];
19+
mov [ebx + findloadlibrarya], eax;
20+
call [ebx + findgetprocaddress];
21+
mov [ebx + findgetprocaddress], eax;
22+
23+
// bind iat
24+
push [ebx + findgetprocaddress]; // arg3, getprocaddress
25+
push [ebx + findloadlibrarya]; // arg2, loadlibraryas
26+
push [ebx + dllbase]; // arg1, dllbase value
27+
call [ebx + membindiat];
28+
add esp, 0xc;
29+
30+
// bind tls
31+
xor edx, edx;
32+
inc edx; // arg2, reason for tls
33+
push edx;
34+
push [ebx + dllbase] // arg1, dllbase
35+
call [ebx + membindtls]
36+
add esp, 0x8;
37+
38+
// call dll oep, for dll entry
39+
xor eax, eax;
40+
push eax; // lpvReserved
41+
inc eax;
42+
push eax; // fdwReason, DLL_PROCESS_ATTACH
43+
push [ebx + dllbase]; // hinstDLL
44+
call [ebx+dlloepva];
45+
46+
// jmp to origin oep
47+
jmp [ebx+exeoepva];
48+
49+
geteip:
50+
mov eax, [esp]
51+
ret
52+
53+
exeoepva: nop;nop;nop;nop;
54+
dllbase: nop;nop;nop;nop;
55+
dlloepva: nop;nop;nop;nop;
56+
memreloc: nop;nop;nop;nop;
57+
membindiat: nop;nop;nop;nop;
58+
membindtls: nop;nop;nop;nop;
59+
findloadlibrarya: nop;nop;nop;nop;
60+
findgetprocaddress: nop;nop;nop;nop;
61+
"""
62+
print("gen_oepinit_code32", code_str)
63+
payload, _ = ks.asm(code_str)
64+
print("payload: ", [hex(x) for x in payload])
65+
return payload
7366

7467
def gen_oepinit_code64():
75-
ks = Ks(KS_ARCH_X86, KS_MODE_64)
76-
code_str = f"""
77-
// for relative address, get the base of addr
78-
call geteip;
79-
lea rbx, [rax-5];
80-
push rcx;
81-
push rdx;
82-
push r8;
83-
push r9;
84-
sub rsp, 0x28; // this is for memory 0x10 align
85-
86-
// get loadlibrarya, getprocaddress
87-
call [rbx + findloadlibrarya];
88-
mov [rbx + findloadlibrarya], rax;
89-
call [rbx + findgetprocaddress];
90-
mov [rbx + findgetprocaddress], rax;
91-
92-
// bind iat
93-
mov r8, [rbx + findgetprocaddress]; // arg3, getprocaddress
94-
mov rdx, [rbx + findloadlibrarya]; // arg2, loadlibraryas
95-
mov rcx, [rbx + dllbase]; // arg1, dllbase value
96-
call [rbx + membindiat];
97-
98-
// bind tls
99-
xor rdx, rdx;
100-
inc rdx; // argc, reason for tls
101-
mov rcx, [rbx + dllbase] // arg1, dllbase
102-
call [rbx + membindtls]
103-
104-
// call dll oep, for dll entry
105-
xor r8, r8; // lpvReserved
106-
xor rdx, rdx;
107-
inc rdx; // fdwReason, DLL_PROCESS_ATTACH
108-
mov rcx, [rbx + dllbase]; // hinstDLL
109-
call [rbx+dlloepva];
110-
111-
// jmp to origin oep
112-
add rsp, 0x28;
113-
pop r9;
114-
pop r8;
115-
pop rdx;
116-
pop rcx;
117-
jmp [rbx+exeoepva];
118-
119-
geteip:
120-
mov rax, [rsp]
121-
ret
122-
123-
exeoepva: nop;nop;nop;nop;nop;nop;nop;nop;
124-
dllbase: nop;nop;nop;nop;nop;nop;nop;nop;
125-
dlloepva: nop;nop;nop;nop;nop;nop;nop;nop;
126-
memreloc: nop;nop;nop;nop;nop;nop;nop;nop;
127-
membindiat: nop;nop;nop;nop;nop;nop;nop;nop;
128-
membindtls: nop;nop;nop;nop;nop;nop;nop;nop;
129-
findloadlibrarya: nop;nop;nop;nop;nop;nop;nop;nop;
130-
findgetprocaddress: nop;nop;nop;nop;nop;nop;nop;nop;
131-
"""
132-
print("gen_oepinit_code64", code_str)
133-
payload, _ = ks.asm(code_str)
134-
print("payload: ", [hex(x) for x in payload])
135-
return payload
68+
ks = Ks(KS_ARCH_X86, KS_MODE_64)
69+
code_str = f"""
70+
// for relative address, get the base of addr
71+
call geteip;
72+
lea rbx, [rax-5];
73+
push rcx;
74+
push rdx;
75+
push r8;
76+
push r9;
77+
sub rsp, 0x28; // this is for memory 0x10 align
78+
79+
// get loadlibrarya, getprocaddress
80+
call [rbx + findloadlibrarya];
81+
mov [rbx + findloadlibrarya], rax;
82+
call [rbx + findgetprocaddress];
83+
mov [rbx + findgetprocaddress], rax;
84+
85+
// bind iat
86+
mov r8, [rbx + findgetprocaddress]; // arg3, getprocaddress
87+
mov rdx, [rbx + findloadlibrarya]; // arg2, loadlibraryas
88+
mov rcx, [rbx + dllbase]; // arg1, dllbase value
89+
call [rbx + membindiat];
90+
91+
// bind tls
92+
xor rdx, rdx;
93+
inc rdx; // argc, reason for tls
94+
mov rcx, [rbx + dllbase] // arg1, dllbase
95+
call [rbx + membindtls]
96+
97+
// call dll oep, for dll entry
98+
xor r8, r8; // lpvReserved
99+
xor rdx, rdx;
100+
inc rdx; // fdwReason, DLL_PROCESS_ATTACH
101+
mov rcx, [rbx + dllbase]; // hinstDLL
102+
call [rbx+dlloepva];
103+
104+
// jmp to origin oep
105+
add rsp, 0x28;
106+
pop r9;
107+
pop r8;
108+
pop rdx;
109+
pop rcx;
110+
jmp [rbx+exeoepva];
111+
112+
geteip:
113+
mov rax, [rsp]
114+
ret
115+
116+
exeoepva: nop;nop;nop;nop;nop;nop;nop;nop;
117+
dllbase: nop;nop;nop;nop;nop;nop;nop;nop;
118+
dlloepva: nop;nop;nop;nop;nop;nop;nop;nop;
119+
memreloc: nop;nop;nop;nop;nop;nop;nop;nop;
120+
membindiat: nop;nop;nop;nop;nop;nop;nop;nop;
121+
membindtls: nop;nop;nop;nop;nop;nop;nop;nop;
122+
findloadlibrarya: nop;nop;nop;nop;nop;nop;nop;nop;
123+
findgetprocaddress: nop;nop;nop;nop;nop;nop;nop;nop;
124+
"""
125+
print("gen_oepinit_code64", code_str)
126+
payload, _ = ks.asm(code_str)
127+
print("payload: ", [hex(x) for x in payload])
128+
return payload
136129

137130
def inject_shellcodestubs(srcpath, libwinpepath, targetpath):
138-
pedll = lief.parse(libwinpepath)
139-
pedll_oph = pedll.optional_header
140-
141-
# generate oepint shellcode
142-
if pedll_oph.magic == lief.PE.PE_TYPE.PE32_PLUS:
143-
oepinit_code = gen_oepinit_code64()
144-
pass
145-
elif pedll_oph.magic == lief.PE.PE_TYPE.PE32:
146-
oepinit_code = gen_oepinit_code32()
147-
pass
148-
else:
149-
print("error invalid pe magic!", pedll_oph.magic)
150-
return
151-
# if len(oepinit_code) < 0x200: oepinit_code.extend([0x00] * (0x200 - len(oepinit_code)))
152-
153-
# find necessary functions
154-
FUNC_SIZE =0x400
155-
codes = {"winpe_memreloc": 0,
156-
"winpe_membindiat": 0,
157-
"winpe_membindtls": 0,
158-
"winpe_findloadlibrarya": 0,
159-
"winpe_findgetprocaddress": 0}
160-
for k in codes.keys():
161-
func = next(filter(lambda e : e.name == k,
162-
pedll.exported_functions))
163-
codes[k] = pedll.get_content_from_virtual_address(
164-
func.address, FUNC_SIZE)
165-
codes['winpe_oepinit'] = oepinit_code
166-
167-
# write shellcode to c source file
168-
with open(srcpath, "rb") as fp:
169-
srctext = fp.read().decode('utf8')
170-
for k, v in codes.items():
171-
k = k.replace("winpe_", "")
172-
_codetext = ",".join([hex(x) for x in v])
173-
srctext = re.sub("g_" + k + r"_code(.+?)(\{0x90\})",
174-
"g_" + k + r"_code\1{" + _codetext +"}", srctext)
175-
with open(targetpath, "wb") as fp:
176-
fp.write(srctext.encode('utf8'))
131+
pedll = lief.parse(libwinpepath)
132+
pedll_oph = pedll.optional_header
133+
134+
# generate oepint shellcode
135+
if pedll_oph.magic == lief.PE.PE_TYPE.PE32_PLUS:
136+
oepinit_code = gen_oepinit_code64()
137+
pass
138+
elif pedll_oph.magic == lief.PE.PE_TYPE.PE32:
139+
oepinit_code = gen_oepinit_code32()
140+
pass
141+
else:
142+
print("error invalid pe magic!", pedll_oph.magic)
143+
return
144+
# if len(oepinit_code) < 0x200: oepinit_code.extend([0x00] * (0x200 - len(oepinit_code)))
145+
146+
# find necessary functions
147+
FUNC_SIZE =0x400
148+
codes = {"winpe_memreloc": 0,
149+
"winpe_membindiat": 0,
150+
"winpe_membindtls": 0,
151+
"winpe_findloadlibrarya": 0,
152+
"winpe_findgetprocaddress": 0}
153+
for k in codes.keys():
154+
func = next(filter(lambda e : e.name == k,
155+
pedll.exported_functions))
156+
codes[k] = pedll.get_content_from_virtual_address(
157+
func.address, FUNC_SIZE)
158+
codes['winpe_oepinit'] = oepinit_code
159+
160+
# write shellcode to c source file
161+
with open(srcpath, "rb") as fp:
162+
srctext = fp.read().decode('utf8')
163+
for k, v in codes.items():
164+
k = k.replace("winpe_", "")
165+
_codetext = ",".join([hex(x) for x in v])
166+
srctext = re.sub("g_" + k + r"_code(.+?)(\{0x90\})",
167+
"g_" + k + r"_code\1{" + _codetext +"}", srctext)
168+
with open(targetpath, "wb") as fp:
169+
fp.write(srctext.encode('utf8'))
177170

178171
def debug():
179-
inject_shellcodestubs("win_injectmemdll.c",
180-
"./bin/libwinpe64.dll",
181-
"./bin/_64win_injectmemdll.c")
182-
pass
172+
inject_shellcodestubs("win_injectmemdll.c",
173+
"./bin/libwinpe64.dll",
174+
"./bin/_64win_injectmemdll.c")
175+
pass
183176

184177
def main():
185-
if len(sys.argv) < 4:
186-
print("win_injectmemdll_shellcodestub srcpath libwinpedllpath outpath")
187-
return
188-
inject_shellcodestubs(sys.argv[1],
189-
sys.argv[2].replace("d.dll", ".dll"), sys.argv[3])
190-
pass
178+
if len(sys.argv) < 4:
179+
print("win_injectmemdll_shellcodestub srcpath libwinpedllpath outpath")
180+
return
181+
inject_shellcodestubs(sys.argv[1],
182+
sys.argv[2].replace("d.dll", ".dll"), sys.argv[3])
183+
pass
191184

192185
if __name__ == "__main__":
193-
# debug()
194-
main()
195-
pass
186+
# debug()
187+
main()
188+
pass
189+
190+
"""
191+
history:
192+
v0.1, initial version
193+
v0.2, add more function for shellcode
194+
v0.3, x86 and x64 no need to use exe's LoadLibraryA
195+
v0.3.1, fix x64 attach dll crash by align stack with 0x10
196+
v0.3.2, add support for ordinal iat and tls
197+
"""

util

Submodule util updated from 38cbf3a to 9960529

0 commit comments

Comments
 (0)