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"""
125import re
136import sys
147import lief
158from keystone import Ks , KS_ARCH_X86 , KS_MODE_32 , KS_MODE_64
169
1710def 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
7467def 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
137130def 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
178171def 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
184177def 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
192185if __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+ """
0 commit comments