Rev 1906 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1906 | Rev 1907 | ||
---|---|---|---|
1 | #include |
1 | #include |
2 | #include |
2 | #include |
3 | #include |
3 | #include |
4 | #include |
4 | #include |
5 | #include |
5 | #include |
6 | #include |
6 | #include |
7 | #include |
7 | #include |
8 | 8 | ||
9 | #include |
9 | #include |
10 | 10 | ||
11 | #include "list.h" |
11 | #include "list.h" |
12 | #include "pe.h" |
12 | #include "pe.h" |
13 | 13 | ||
14 | #define unlikely(x) __builtin_expect(!!(x), 0) |
14 | #define unlikely(x) __builtin_expect(!!(x), 0) |
15 | 15 | ||
16 | //#define DBG(format,...) printf(format,##__VA_ARGS__) |
16 | //#define DBG(format,...) printf(format,##__VA_ARGS__) |
17 | 17 | ||
18 | #define DBG(format,...) |
18 | #define DBG(format,...) |
19 | 19 | ||
20 | 20 | ||
21 | void __fastcall init_loader(void *libc_image); |
21 | void __fastcall init_loader(void *libc_image); |
22 | void* __fastcall create_image(void *raw); |
22 | void* __fastcall create_image(void *raw); |
23 | int __fastcall link_image(void *img_base); |
23 | int __fastcall link_image(void *img_base); |
24 | int __fastcall do_exec(uint32_t my_app, uint32_t *params); |
24 | int __fastcall do_exec(uint32_t my_app, uint32_t *params); |
25 | 25 | ||
26 | 26 | ||
27 | extern char* __appenv; |
27 | extern char* __appenv; |
28 | extern int __appenv_size; |
28 | extern int __appenv_size; |
29 | 29 | ||
30 | typedef struct tag_module module_t; |
30 | typedef struct tag_module module_t; |
31 | 31 | ||
32 | struct app_hdr |
32 | struct app_hdr |
33 | { |
33 | { |
34 | char banner[8]; |
34 | char banner[8]; |
35 | int version; |
35 | int version; |
36 | int start; |
36 | int start; |
37 | int iend; |
37 | int iend; |
38 | int memsize; |
38 | int memsize; |
39 | int stacktop; |
39 | int stacktop; |
40 | char *cmdline; |
40 | char *cmdline; |
41 | char *path; |
41 | char *path; |
42 | }; |
42 | }; |
43 | 43 | ||
44 | struct tag_module |
44 | struct tag_module |
45 | { |
45 | { |
46 | struct list_head list; |
46 | struct list_head list; |
47 | 47 | ||
48 | char *img_name; |
48 | char *img_name; |
49 | char *img_path; |
49 | char *img_path; |
50 | 50 | ||
51 | uint32_t refcount; |
51 | uint32_t refcount; |
52 | 52 | ||
53 | void *start; |
53 | void *start; |
54 | uint32_t end; |
54 | uint32_t end; |
55 | 55 | ||
56 | void *entry; |
56 | void *entry; |
57 | 57 | ||
58 | PIMAGE_NT_HEADERS32 img_hdr; |
58 | PIMAGE_NT_HEADERS32 img_hdr; |
59 | PIMAGE_SECTION_HEADER img_sec; |
59 | PIMAGE_SECTION_HEADER img_sec; |
60 | PIMAGE_EXPORT_DIRECTORY img_exp; |
60 | PIMAGE_EXPORT_DIRECTORY img_exp; |
61 | }; |
61 | }; |
62 | 62 | ||
63 | typedef struct |
63 | typedef struct |
64 | { |
64 | { |
65 | struct list_head list; |
65 | struct list_head list; |
66 | char *path; |
66 | char *path; |
67 | int path_len; |
67 | int path_len; |
68 | }dll_path_t; |
68 | }dll_path_t; |
69 | 69 | ||
70 | module_t* load_module(const char *name); |
70 | module_t* load_module(const char *name); |
71 | 71 | ||
72 | LIST_HEAD(dll_list); |
72 | LIST_HEAD(dll_list); |
73 | LIST_HEAD(path_list); |
73 | LIST_HEAD(path_list); |
74 | 74 | ||
75 | static module_t libc_dll; |
75 | static module_t libc_dll; |
76 | static char libc_name[] = "libc.dll"; |
76 | static char libc_name[] = "libc.dll"; |
77 | static char libc_path[] = "/sys/lib/libc.dll"; |
77 | static char libc_path[] = "/sys/lib/libc.dll"; |
78 | 78 | ||
79 | static inline int IsPowerOf2(uint32_t val) |
79 | static inline int IsPowerOf2(uint32_t val) |
80 | { |
80 | { |
81 | if(val == 0) |
81 | if(val == 0) |
82 | return 0; |
82 | return 0; |
83 | return (val & (val - 1)) == 0; |
83 | return (val & (val - 1)) == 0; |
84 | } |
84 | } |
85 | 85 | ||
86 | 86 | ||
87 | int validate_pe(void *raw, size_t raw_size, int is_exec) |
87 | int validate_pe(void *raw, size_t raw_size, int is_exec) |
88 | { |
88 | { |
89 | PIMAGE_DOS_HEADER dos; |
89 | PIMAGE_DOS_HEADER dos; |
90 | PIMAGE_NT_HEADERS32 nt; |
90 | PIMAGE_NT_HEADERS32 nt; |
91 | 91 | ||
92 | dos = (PIMAGE_DOS_HEADER)raw; |
92 | dos = (PIMAGE_DOS_HEADER)raw; |
93 | 93 | ||
94 | if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) ) |
94 | if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) ) |
95 | return 0; |
95 | return 0; |
96 | 96 | ||
97 | if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0) |
97 | if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0) |
98 | return 0; |
98 | return 0; |
99 | 99 | ||
100 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
100 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
101 | 101 | ||
102 | if( (uint32_t)nt < (uint32_t)raw) |
102 | if( (uint32_t)nt < (uint32_t)raw) |
103 | return 0; |
103 | return 0; |
104 | 104 | ||
105 | if(nt->Signature != IMAGE_NT_SIGNATURE) |
105 | if(nt->Signature != IMAGE_NT_SIGNATURE) |
106 | return 0; |
106 | return 0; |
107 | 107 | ||
108 | if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) |
108 | if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) |
109 | return 0; |
109 | return 0; |
110 | 110 | ||
111 | if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) |
111 | if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) |
112 | return 0; |
112 | return 0; |
113 | 113 | ||
114 | if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) |
114 | if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) |
115 | return 0; |
115 | return 0; |
116 | 116 | ||
117 | if( is_exec && nt->OptionalHeader.ImageBase != 0) |
117 | if( is_exec && nt->OptionalHeader.ImageBase != 0) |
118 | return 0; |
118 | return 0; |
119 | 119 | ||
120 | if(nt->OptionalHeader.SectionAlignment < 4096) |
120 | if(nt->OptionalHeader.SectionAlignment < 4096) |
121 | { |
121 | { |
122 | if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) |
122 | if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) |
123 | return 0; |
123 | return 0; |
124 | } |
124 | } |
125 | else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment) |
125 | else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment) |
126 | return 0; |
126 | return 0; |
127 | 127 | ||
128 | if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) || |
128 | if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) || |
129 | !IsPowerOf2(nt->OptionalHeader.FileAlignment)) |
129 | !IsPowerOf2(nt->OptionalHeader.FileAlignment)) |
130 | return 0; |
130 | return 0; |
131 | 131 | ||
132 | if(nt->FileHeader.NumberOfSections > 96) |
132 | if(nt->FileHeader.NumberOfSections > 96) |
133 | return 0; |
133 | return 0; |
134 | 134 | ||
135 | return 1; |
135 | return 1; |
136 | } |
136 | } |
137 | 137 | ||
138 | 138 | ||
139 | void __fastcall init_loader(void *libc_image) |
139 | void __fastcall init_loader(void *libc_image) |
140 | { |
140 | { |
141 | 141 | ||
142 | PIMAGE_DOS_HEADER dos; |
142 | PIMAGE_DOS_HEADER dos; |
143 | PIMAGE_NT_HEADERS32 nt; |
143 | PIMAGE_NT_HEADERS32 nt; |
144 | PIMAGE_EXPORT_DIRECTORY exp; |
144 | PIMAGE_EXPORT_DIRECTORY exp; |
145 | 145 | ||
146 | struct app_hdr *header; |
146 | struct app_hdr *header; |
147 | 147 | ||
148 | dll_path_t *path; |
148 | dll_path_t *path; |
149 | int len; |
149 | int len; |
150 | char *p; |
150 | char *p; |
151 | 151 | ||
152 | if(__appenv_size) |
152 | if(__appenv_size) |
153 | { |
153 | { |
154 | char *env; |
154 | char *env; |
155 | env = envz_get(__appenv, __appenv_size, "PATH"); |
155 | env = envz_get(__appenv, __appenv_size, "PATH"); |
156 | if( env ) |
156 | if( env ) |
157 | { |
157 | { |
158 | while( *env ) |
158 | while( *env ) |
159 | { |
159 | { |
160 | p = env; |
160 | p = env; |
161 | while(*p) |
161 | while(*p) |
162 | { |
162 | { |
163 | if( *p == 0x0D) |
163 | if( *p == 0x0D) |
164 | break; |
164 | break; |
165 | else if( *p == 0x0A) |
165 | else if( *p == 0x0A) |
166 | break; |
166 | break; |
167 | else if( *p == ':') |
167 | else if( *p == ':') |
168 | break; |
168 | break; |
169 | p++; |
169 | p++; |
170 | }; |
170 | }; |
171 | len = p-env; |
171 | len = p-env; |
172 | if(len) |
172 | if(len) |
173 | { |
173 | { |
174 | char *p1; |
174 | char *p1; |
175 | 175 | ||
176 | p1 = (char*)malloc(len+1); |
176 | p1 = (char*)malloc(len+1); |
177 | memcpy(p1, env, len); |
177 | memcpy(p1, env, len); |
178 | p1[len]=0; |
178 | p1[len]=0; |
179 | 179 | ||
180 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
180 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
181 | INIT_LIST_HEAD(&path->list); |
181 | INIT_LIST_HEAD(&path->list); |
182 | path->path = p1; |
182 | path->path = p1; |
183 | path->path_len = len; |
183 | path->path_len = len; |
184 | DBG("add libraries path %s\n", path->path); |
184 | DBG("add libraries path %s\n", path->path); |
185 | list_add_tail(&path->list, &path_list); |
185 | list_add_tail(&path->list, &path_list); |
186 | }; |
186 | }; |
187 | if(*p == ':') |
187 | if(*p == ':') |
188 | { |
188 | { |
189 | env = p+1; |
189 | env = p+1; |
190 | continue; |
190 | continue; |
191 | } |
191 | } |
192 | else break; |
192 | else break; |
193 | }; |
193 | }; |
194 | }; |
194 | }; |
195 | }; |
195 | }; |
196 | 196 | ||
197 | header = (struct app_hdr*)NULL; |
197 | header = (struct app_hdr*)NULL; |
198 | 198 | ||
199 | len = strrchr(header->path, '/') - header->path+1; |
199 | len = strrchr(header->path, '/') - header->path+1; |
200 | p = (char*)malloc(len+1); |
200 | p = (char*)malloc(len+1); |
201 | memcpy(p, header->path, len); |
201 | memcpy(p, header->path, len); |
202 | p[len]=0; |
202 | p[len]=0; |
203 | 203 | ||
204 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
204 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
205 | INIT_LIST_HEAD(&path->list); |
205 | INIT_LIST_HEAD(&path->list); |
206 | path->path = p; |
206 | path->path = p; |
207 | path->path_len = len; |
207 | path->path_len = len; |
208 | DBG("add libraries path %s\n", path->path); |
208 | DBG("add libraries path %s\n", path->path); |
209 | list_add_tail(&path->list, &path_list); |
209 | list_add_tail(&path->list, &path_list); |
210 | 210 | ||
211 | 211 | ||
212 | #if 0 |
212 | #if 0 |
213 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
213 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
214 | INIT_LIST_HEAD(&path->list); |
214 | INIT_LIST_HEAD(&path->list); |
215 | path->path = "/sys/lib/"; |
215 | path->path = "/sys/lib/"; |
216 | path->path_len = 9; /* FIXME */ |
216 | path->path_len = 9; /* FIXME */ |
217 | DBG("add libraries path %s\n", path->path); |
217 | DBG("add libraries path %s\n", path->path); |
218 | list_add_tail(&path->list, &path_list); |
218 | list_add_tail(&path->list, &path_list); |
219 | #endif |
219 | #endif |
220 | 220 | ||
221 | INIT_LIST_HEAD(&libc_dll.list); |
221 | INIT_LIST_HEAD(&libc_dll.list); |
222 | 222 | ||
223 | libc_dll.img_name = libc_name; |
223 | libc_dll.img_name = libc_name; |
224 | libc_dll.img_path = libc_path; |
224 | libc_dll.img_path = libc_path; |
225 | 225 | ||
226 | libc_dll.refcount = 1; |
226 | libc_dll.refcount = 1; |
227 | 227 | ||
228 | dos = (PIMAGE_DOS_HEADER)libc_image; |
228 | dos = (PIMAGE_DOS_HEADER)libc_image; |
229 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
229 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
230 | exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, libc_image, |
230 | exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, libc_image, |
231 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
231 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
232 | 232 | ||
233 | libc_dll.start = libc_image; |
233 | libc_dll.start = libc_image; |
234 | libc_dll.end = MakePtr(uint32_t,libc_image, nt->OptionalHeader.SizeOfImage); |
234 | libc_dll.end = MakePtr(uint32_t,libc_image, nt->OptionalHeader.SizeOfImage); |
235 | 235 | ||
236 | libc_dll.img_hdr = nt; |
236 | libc_dll.img_hdr = nt; |
237 | libc_dll.img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); |
237 | libc_dll.img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); |
238 | libc_dll.img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,libc_image, |
238 | libc_dll.img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,libc_image, |
239 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
239 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
240 | 240 | ||
241 | list_add_tail(&libc_dll.list, &dll_list); |
241 | list_add_tail(&libc_dll.list, &dll_list); |
242 | }; |
242 | }; |
243 | 243 | ||
244 | const module_t* find_module(const char *name) |
244 | const module_t* find_module(const char *name) |
245 | { |
245 | { |
246 | module_t* mod; |
246 | module_t* mod; |
247 | 247 | ||
248 | list_for_each_entry(mod, &dll_list, list) |
248 | list_for_each_entry(mod, &dll_list, list) |
249 | { |
249 | { |
250 | if( !strncmp(name, mod->img_name, 16)) |
250 | if( !strncmp(name, mod->img_name, 16)) |
251 | return mod; |
251 | return mod; |
252 | }; |
252 | }; |
253 | 253 | ||
254 | return load_module(name); |
254 | return load_module(name); |
255 | }; |
255 | }; |
256 | 256 | ||
257 | static inline void sec_copy(void *dst, void *src, size_t len) |
257 | static inline void sec_copy(void *dst, void *src, size_t len) |
258 | { |
258 | { |
259 | __asm__ __volatile__ ( |
259 | __asm__ __volatile__ ( |
260 | "shrl $2, %%ecx \n\t" |
260 | "shrl $2, %%ecx \n\t" |
261 | "rep movsl" |
261 | "rep movsl" |
262 | : |
262 | : |
263 | :"c"(len),"S"(src),"D"(dst) |
263 | :"c"(len),"S"(src),"D"(dst) |
264 | :"cc"); |
264 | :"cc"); |
265 | __asm__ __volatile__ ( |
265 | __asm__ __volatile__ ( |
266 | "" |
266 | "" |
267 | :::"ecx","esi","edi"); |
267 | :::"ecx","esi","edi"); |
268 | }; |
268 | }; |
269 | 269 | ||
270 | static inline void *user_alloc(size_t size) |
270 | static inline void *user_alloc(size_t size) |
271 | { |
271 | { |
272 | void *val; |
272 | void *val; |
273 | __asm__ __volatile__( |
273 | __asm__ __volatile__( |
274 | "int $0x40" |
274 | "int $0x40" |
275 | :"=eax"(val) |
275 | :"=eax"(val) |
276 | :"a"(68),"b"(12),"c"(size)); |
276 | :"a"(68),"b"(12),"c"(size)); |
277 | return val; |
277 | return val; |
278 | } |
278 | } |
279 | 279 | ||
280 | void* __fastcall create_image(void *raw) |
280 | void* __fastcall create_image(void *raw) |
281 | { |
281 | { |
282 | PIMAGE_DOS_HEADER dos; |
282 | PIMAGE_DOS_HEADER dos; |
283 | PIMAGE_NT_HEADERS32 nt; |
283 | PIMAGE_NT_HEADERS32 nt; |
284 | PIMAGE_SECTION_HEADER img_sec; |
284 | PIMAGE_SECTION_HEADER img_sec; |
285 | 285 | ||
286 | void *img_base; |
286 | void *img_base; |
287 | uint32_t sec_align; |
287 | uint32_t sec_align; |
288 | int i; |
288 | int i; |
289 | 289 | ||
290 | dos = (PIMAGE_DOS_HEADER)raw; |
290 | dos = (PIMAGE_DOS_HEADER)raw; |
291 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
291 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
292 | 292 | ||
293 | img_base = user_alloc(nt->OptionalHeader.SizeOfImage); |
293 | img_base = user_alloc(nt->OptionalHeader.SizeOfImage); |
294 | 294 | ||
295 | if(unlikely(img_base == NULL)) |
295 | if(unlikely(img_base == NULL)) |
296 | return 0; |
296 | return 0; |
297 | 297 | ||
298 | sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders); |
298 | sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders); |
299 | 299 | ||
300 | img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32)); |
300 | img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32)); |
301 | 301 | ||
302 | sec_align = nt->OptionalHeader.SectionAlignment; |
302 | sec_align = nt->OptionalHeader.SectionAlignment; |
303 | 303 | ||
304 | for(i=0; i< nt->FileHeader.NumberOfSections; i++) |
304 | for(i=0; i< nt->FileHeader.NumberOfSections; i++) |
305 | { |
305 | { |
306 | void *src_ptr; |
306 | void *src_ptr; |
307 | void *dest_ptr; |
307 | void *dest_ptr; |
308 | size_t sec_size; |
308 | size_t sec_size; |
309 | 309 | ||
310 | if ( img_sec->SizeOfRawData && img_sec->PointerToRawData ) |
310 | if ( img_sec->SizeOfRawData && img_sec->PointerToRawData ) |
311 | { |
311 | { |
312 | src_ptr = MakePtr(void*, raw, img_sec->PointerToRawData); |
312 | src_ptr = MakePtr(void*, raw, img_sec->PointerToRawData); |
313 | dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress); |
313 | dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress); |
314 | sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData); |
314 | sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData); |
315 | }; |
315 | }; |
316 | 316 | ||
317 | img_sec++; |
317 | img_sec++; |
318 | }; |
318 | }; |
319 | 319 | ||
320 | if(nt->OptionalHeader.DataDirectory[5].Size) |
320 | if(nt->OptionalHeader.DataDirectory[5].Size) |
321 | { |
321 | { |
322 | PIMAGE_BASE_RELOCATION reloc; |
322 | PIMAGE_BASE_RELOCATION reloc; |
323 | 323 | ||
324 | uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase; |
324 | uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase; |
325 | 325 | ||
326 | reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base, |
326 | reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base, |
327 | nt->OptionalHeader.DataDirectory[5].VirtualAddress); |
327 | nt->OptionalHeader.DataDirectory[5].VirtualAddress); |
328 | 328 | ||
329 | while ( reloc->SizeOfBlock != 0 ) |
329 | while ( reloc->SizeOfBlock != 0 ) |
330 | { |
330 | { |
331 | uint32_t cnt; |
331 | uint32_t cnt; |
332 | uint16_t *entry; |
332 | uint16_t *entry; |
333 | uint16_t reltype; |
333 | uint16_t reltype; |
334 | uint32_t offs; |
334 | uint32_t offs; |
335 | 335 | ||
336 | cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t); |
336 | cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t); |
337 | entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) ); |
337 | entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) ); |
338 | 338 | ||
339 | for ( i=0; i < cnt; i++ ) |
339 | for ( i=0; i < cnt; i++ ) |
340 | { |
340 | { |
341 | uint16_t *p16; |
341 | uint16_t *p16; |
342 | uint32_t *p32; |
342 | uint32_t *p32; |
343 | 343 | ||
344 | reltype = (*entry & 0xF000) >> 12; |
344 | reltype = (*entry & 0xF000) >> 12; |
345 | offs = (*entry & 0x0FFF) + reloc->VirtualAddress; |
345 | offs = (*entry & 0x0FFF) + reloc->VirtualAddress; |
346 | switch(reltype) |
346 | switch(reltype) |
347 | { |
347 | { |
348 | case 1: |
348 | case 1: |
349 | p16 = MakePtr(uint16_t*, img_base, offs); |
349 | p16 = MakePtr(uint16_t*, img_base, offs); |
350 | *p16+= (uint16_t)(delta>>16); |
350 | *p16+= (uint16_t)(delta>>16); |
351 | break; |
351 | break; |
352 | case 2: |
352 | case 2: |
353 | p16 = MakePtr(uint16_t*, img_base, offs); |
353 | p16 = MakePtr(uint16_t*, img_base, offs); |
354 | *p16+= (uint16_t)delta; |
354 | *p16+= (uint16_t)delta; |
355 | break; |
355 | break; |
356 | case 3: |
356 | case 3: |
357 | p32 = MakePtr(uint32_t*, img_base, offs); |
357 | p32 = MakePtr(uint32_t*, img_base, offs); |
358 | *p32+= delta; |
358 | *p32+= delta; |
359 | } |
359 | } |
360 | entry++; |
360 | entry++; |
361 | } |
361 | } |
362 | reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock); |
362 | reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock); |
363 | } |
363 | } |
364 | }; |
364 | }; |
365 | return img_base; |
365 | return img_base; |
366 | }; |
366 | }; |
367 | 367 | ||
368 | int __fastcall link_image(void *img_base) |
368 | int __fastcall link_image(void *img_base) |
369 | { |
369 | { |
370 | static jmp_buf loader_env; |
370 | static jmp_buf loader_env; |
371 | static recursion = -1; |
371 | static recursion = -1; |
372 | 372 | ||
373 | PIMAGE_DOS_HEADER dos; |
373 | PIMAGE_DOS_HEADER dos; |
374 | PIMAGE_NT_HEADERS32 nt; |
374 | PIMAGE_NT_HEADERS32 nt; |
375 | int warn = 0; |
375 | int warn = 0; |
376 | 376 | ||
377 | recursion++; |
377 | recursion++; |
378 | if( !recursion ) |
378 | if( !recursion ) |
379 | { |
379 | { |
380 | if( unlikely(setjmp(loader_env) != 0)) |
380 | if( unlikely(setjmp(loader_env) != 0)) |
381 | { |
381 | { |
382 | recursion = -1; |
382 | recursion = -1; |
383 | return 0; |
383 | return 0; |
384 | }; |
384 | }; |
385 | }; |
385 | }; |
386 | 386 | ||
387 | dos = (PIMAGE_DOS_HEADER)img_base; |
387 | dos = (PIMAGE_DOS_HEADER)img_base; |
388 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
388 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
389 | 389 | ||
390 | if(nt->OptionalHeader.DataDirectory[1].Size) |
390 | if(nt->OptionalHeader.DataDirectory[1].Size) |
391 | { |
391 | { |
392 | PIMAGE_IMPORT_DESCRIPTOR imp; |
392 | PIMAGE_IMPORT_DESCRIPTOR imp; |
393 | 393 | ||
394 | imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base, |
394 | imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base, |
395 | nt->OptionalHeader.DataDirectory[1].VirtualAddress); |
395 | nt->OptionalHeader.DataDirectory[1].VirtualAddress); |
396 | 396 | ||
397 | while ( imp->Name ) |
397 | while ( imp->Name ) |
398 | { |
398 | { |
399 | PIMAGE_DOS_HEADER expdos; |
399 | PIMAGE_DOS_HEADER expdos; |
400 | PIMAGE_NT_HEADERS32 expnt; |
400 | PIMAGE_NT_HEADERS32 expnt; |
401 | PIMAGE_EXPORT_DIRECTORY exp; |
401 | PIMAGE_EXPORT_DIRECTORY exp; |
402 | PIMAGE_THUNK_DATA32 thunk; |
402 | PIMAGE_THUNK_DATA32 thunk; |
403 | 403 | ||
404 | void **iat; |
404 | void **iat; |
405 | char *libname; |
405 | char *libname; |
406 | uint32_t *exp_functions; |
406 | uint32_t *exp_functions; |
407 | uint16_t *exp_ordinals; |
407 | uint16_t *exp_ordinals; |
408 | char **exp_names; |
408 | char **exp_names; |
409 | 409 | ||
410 | const module_t *api; |
410 | const module_t *api; |
411 | 411 | ||
412 | libname=MakePtr(char*,imp->Name, img_base); |
412 | libname=MakePtr(char*,imp->Name, img_base); |
413 | 413 | ||
414 | DBG("import from %s\n",libname); |
414 | DBG("import from %s\n",libname); |
415 | 415 | ||
416 | api = find_module(libname); |
416 | api = find_module(libname); |
417 | if(unlikely(api == NULL)) |
417 | if(unlikely(api == NULL)) |
418 | { |
418 | { |
419 | printf("library %s not found\n", libname); |
419 | printf("library %s not found\n", libname); |
420 | longjmp(loader_env, 1); |
420 | longjmp(loader_env, 1); |
421 | } |
421 | } |
422 | 422 | ||
423 | iat = MakePtr(void**,imp->FirstThunk, img_base); |
423 | iat = MakePtr(void**,imp->FirstThunk, img_base); |
424 | 424 | ||
425 | if(imp->OriginalFirstThunk !=0 ) |
425 | if(imp->OriginalFirstThunk !=0 ) |
426 | { |
426 | { |
427 | thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->OriginalFirstThunk, img_base); |
427 | thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->OriginalFirstThunk, img_base); |
428 | } |
428 | } |
429 | else |
429 | else |
430 | { |
430 | { |
431 | thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->FirstThunk, img_base); |
431 | thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->FirstThunk, img_base); |
432 | }; |
432 | }; |
433 | 433 | ||
434 | exp = api->img_exp; |
434 | exp = api->img_exp; |
435 | 435 | ||
436 | exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,api->start); |
436 | exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,api->start); |
437 | exp_ordinals = MakePtr(uint16_t*, exp->AddressOfNameOrdinals,api->start); |
437 | exp_ordinals = MakePtr(uint16_t*, exp->AddressOfNameOrdinals,api->start); |
438 | exp_names = MakePtr(char**, exp->AddressOfNames,api->start); |
438 | exp_names = MakePtr(char**, exp->AddressOfNames,api->start); |
439 | 439 | ||
440 | while ( thunk->u1.AddressOfData != 0 ) |
440 | while ( thunk->u1.AddressOfData != 0 ) |
441 | { |
441 | { |
442 | PIMAGE_IMPORT_BY_NAME imp_name; |
442 | PIMAGE_IMPORT_BY_NAME imp_name; |
443 | 443 | ||
444 | if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) |
444 | if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) |
445 | { |
445 | { |
446 | // ordinal = (*func_list) & 0x7fffffff; |
446 | // ordinal = (*func_list) & 0x7fffffff; |
447 | // *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal); |
447 | // *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal); |
448 | // if ((*ImportAddressList) == NULL) |
448 | // if ((*ImportAddressList) == NULL) |
449 | // { |
449 | // { |
450 | // DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName); |
450 | // DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName); |
451 | // RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName); |
451 | // RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName); |
452 | // return STATUS_ENTRYPOINT_NOT_FOUND; |
452 | // return STATUS_ENTRYPOINT_NOT_FOUND; |
453 | // } |
453 | // } |
454 | } |
454 | } |
455 | else |
455 | else |
456 | { |
456 | { |
457 | char *export_name; |
457 | char *export_name; |
458 | uint16_t ordinal; |
458 | uint16_t ordinal; |
459 | void *function; |
459 | void *function; |
460 | uint32_t minn; |
460 | uint32_t minn; |
461 | uint32_t maxn; |
461 | uint32_t maxn; |
462 | 462 | ||
463 | imp_name = MakePtr(PIMAGE_IMPORT_BY_NAME, |
463 | imp_name = MakePtr(PIMAGE_IMPORT_BY_NAME, |
464 | thunk->u1.AddressOfData, img_base); |
464 | thunk->u1.AddressOfData, img_base); |
465 | *iat = NULL; |
465 | *iat = NULL; |
466 | 466 | ||
467 | DBG("import %s", imp_name->Name); |
467 | DBG("import %s", imp_name->Name); |
468 | 468 | ||
469 | if(imp_name->Hint < exp->NumberOfNames) |
469 | if(imp_name->Hint < exp->NumberOfNames) |
470 | { |
470 | { |
471 | export_name = MakePtr(char*,exp_names[imp_name->Hint], |
471 | export_name = MakePtr(char*,exp_names[imp_name->Hint], |
472 | api->start); |
472 | api->start); |
473 | if(strcmp(imp_name->Name, export_name) == 0) |
473 | if(strcmp(imp_name->Name, export_name) == 0) |
474 | { |
474 | { |
475 | ordinal = exp_ordinals[imp_name->Hint]; |
475 | ordinal = exp_ordinals[imp_name->Hint]; |
476 | function = MakePtr(void*,exp_functions[ordinal], api->start); |
476 | function = MakePtr(void*,exp_functions[ordinal], api->start); |
477 | if((uint32_t)function >= (uint32_t)exp) |
477 | if((uint32_t)function >= (uint32_t)exp) |
478 | { |
478 | { |
479 | printf("forward %s\n", function); |
479 | printf("forward %s\n", function); |
480 | warn=1; |
480 | warn=1; |
481 | } |
481 | } |
482 | else |
482 | else |
483 | { |
483 | { |
484 | DBG(" \t\tat %x\n", function); |
484 | DBG(" \t\tat %x\n", function); |
485 | *iat = function; |
485 | *iat = function; |
486 | }; |
486 | }; |
487 | thunk++; // Advance to next thunk |
487 | thunk++; // Advance to next thunk |
488 | iat++; |
488 | iat++; |
489 | continue; |
489 | continue; |
490 | }; |
490 | }; |
491 | }; |
491 | }; |
492 | 492 | ||
493 | 493 | ||
494 | minn = 0; |
494 | minn = 0; |
495 | maxn = exp->NumberOfNames - 1; |
495 | maxn = exp->NumberOfNames - 1; |
496 | while (minn <= maxn) |
496 | while (minn <= maxn) |
497 | { |
497 | { |
498 | int mid; |
498 | int mid; |
499 | int res; |
499 | int res; |
500 | 500 | ||
501 | mid = (minn + maxn) / 2; |
501 | mid = (minn + maxn) / 2; |
502 | 502 | ||
503 | export_name = MakePtr(char*,exp_names[mid],api->start); |
503 | export_name = MakePtr(char*,exp_names[mid],api->start); |
504 | 504 | ||
505 | res = strcmp(export_name, imp_name->Name); |
505 | res = strcmp(export_name, imp_name->Name); |
506 | if (res == 0) |
506 | if (res == 0) |
507 | { |
507 | { |
508 | ordinal = exp_ordinals[mid]; |
508 | ordinal = exp_ordinals[mid]; |
509 | function = MakePtr(void*,exp_functions[ordinal], api->start); |
509 | function = MakePtr(void*,exp_functions[ordinal], api->start); |
510 | 510 | ||
511 | if((uint32_t)function >= (uint32_t)exp) |
511 | if((uint32_t)function >= (uint32_t)exp) |
512 | { |
512 | { |
513 | printf("forward %s\n", function); |
513 | printf("forward %s\n", function); |
514 | warn=1; |
514 | warn=1; |
515 | } |
515 | } |
516 | else |
516 | else |
517 | { |
517 | { |
518 | DBG(" \t\tat %x\n", function); |
518 | DBG(" \t\tat %x\n", function); |
519 | *iat = function; |
519 | *iat = function; |
520 | }; |
520 | }; |
521 | break; |
521 | break; |
522 | } |
522 | } |
523 | else if (minn == maxn) |
523 | else if (minn == maxn) |
524 | { |
524 | { |
525 | printf(" unresolved\n",imp_name->Name); |
525 | printf(" unresolved %s\n",imp_name->Name); |
526 | warn=1; |
526 | warn=1; |
527 | break; |
527 | break; |
528 | } |
528 | } |
529 | else if (res > 0) |
529 | else if (res > 0) |
530 | { |
530 | { |
531 | maxn = mid - 1; |
531 | maxn = mid - 1; |
532 | } |
532 | } |
533 | else |
533 | else |
534 | { |
534 | { |
535 | minn = mid + 1; |
535 | minn = mid + 1; |
536 | } |
536 | } |
537 | }; |
537 | }; |
538 | }; |
538 | }; |
539 | thunk++; // Advance to next thunk |
539 | thunk++; // Advance to next thunk |
540 | iat++; |
540 | iat++; |
541 | } |
541 | } |
542 | imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR |
542 | imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR |
543 | }; |
543 | }; |
544 | }; |
544 | }; |
545 | 545 | ||
546 | recursion--; |
546 | recursion--; |
547 | 547 | ||
548 | if ( !warn ) |
548 | if ( !warn ) |
549 | return 1; |
549 | return 1; |
550 | else |
550 | else |
551 | return 0; |
551 | return 0; |
552 | } |
552 | } |
553 | 553 | ||
554 | void* get_entry_point(void *raw) |
554 | void* get_entry_point(void *raw) |
555 | { |
555 | { |
556 | PIMAGE_DOS_HEADER dos; |
556 | PIMAGE_DOS_HEADER dos; |
557 | PIMAGE_NT_HEADERS32 nt; |
557 | PIMAGE_NT_HEADERS32 nt; |
558 | 558 | ||
559 | dos = (PIMAGE_DOS_HEADER)raw; |
559 | dos = (PIMAGE_DOS_HEADER)raw; |
560 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
560 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
561 | 561 | ||
562 | return MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint); |
562 | return MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint); |
563 | } |
563 | } |
564 | 564 | ||
565 | 565 | ||
566 | module_t* load_module(const char *name) |
566 | module_t* load_module(const char *name) |
567 | { |
567 | { |
568 | char *path; |
568 | char *path; |
569 | int len; |
569 | int len; |
570 | 570 | ||
571 | len = strlen(name); |
571 | len = strlen(name); |
572 | 572 | ||
573 | dll_path_t *dllpath; |
573 | dll_path_t *dllpath; |
574 | 574 | ||
575 | list_for_each_entry(dllpath, &path_list, list) |
575 | list_for_each_entry(dllpath, &path_list, list) |
576 | { |
576 | { |
577 | PIMAGE_DOS_HEADER dos; |
577 | PIMAGE_DOS_HEADER dos; |
578 | PIMAGE_NT_HEADERS32 nt; |
578 | PIMAGE_NT_HEADERS32 nt; |
579 | PIMAGE_EXPORT_DIRECTORY exp; |
579 | PIMAGE_EXPORT_DIRECTORY exp; |
580 | 580 | ||
581 | module_t *module; |
581 | module_t *module; |
582 | void *raw_img; |
582 | void *raw_img; |
583 | size_t raw_size; |
583 | size_t raw_size; |
584 | void *img_base; |
584 | void *img_base; |
585 | 585 | ||
586 | path = alloca(len+dllpath->path_len+1); |
586 | path = alloca(len+dllpath->path_len+1); |
587 | memcpy(path, dllpath->path, dllpath->path_len); |
587 | memcpy(path, dllpath->path, dllpath->path_len); |
588 | 588 | ||
589 | memcpy(path+dllpath->path_len, name, len); |
589 | memcpy(path+dllpath->path_len, name, len); |
590 | path[len+dllpath->path_len]=0; |
590 | path[len+dllpath->path_len]=0; |
591 | 591 | ||
592 | raw_img = load_file(path, &raw_size); |
592 | raw_img = load_file(path, &raw_size); |
593 | if(raw_img == NULL) |
593 | if(raw_img == NULL) |
594 | continue; |
594 | continue; |
595 | 595 | ||
596 | if( validate_pe(raw_img, raw_size, 0) == 0) |
596 | if( validate_pe(raw_img, raw_size, 0) == 0) |
597 | { |
597 | { |
598 | printf("invalide module %s\n", path); |
598 | printf("invalide module %s\n", path); |
599 | user_free(raw_img); |
599 | user_free(raw_img); |
600 | continue; |
600 | continue; |
601 | }; |
601 | }; |
602 | 602 | ||
603 | img_base = create_image(raw_img); |
603 | img_base = create_image(raw_img); |
604 | user_free(raw_img); |
604 | user_free(raw_img); |
605 | 605 | ||
606 | if( unlikely(img_base == NULL) ) |
606 | if( unlikely(img_base == NULL) ) |
607 | { |
607 | { |
608 | printf("cannot create image %s\n",path); |
608 | printf("cannot create image %s\n",path); |
609 | continue; |
609 | continue; |
610 | }; |
610 | }; |
611 | 611 | ||
612 | module = (module_t*)malloc(sizeof(module_t)); |
612 | module = (module_t*)malloc(sizeof(module_t)); |
613 | 613 | ||
614 | if(unlikely(module == NULL)) |
614 | if(unlikely(module == NULL)) |
615 | { |
615 | { |
616 | printf("%s epic fail: no enough memory\n",__FUNCTION__); |
616 | printf("%s epic fail: no enough memory\n",__FUNCTION__); |
617 | user_free(img_base); |
617 | user_free(img_base); |
618 | return 0; |
618 | return 0; |
619 | } |
619 | } |
620 | 620 | ||
621 | INIT_LIST_HEAD(&module->list); |
621 | INIT_LIST_HEAD(&module->list); |
622 | 622 | ||
623 | module->img_name = strdup(name); |
623 | module->img_name = strdup(name); |
624 | module->img_path = strdup(path); |
624 | module->img_path = strdup(path); |
625 | module->start = img_base; |
625 | module->start = img_base; |
626 | module->entry = get_entry_point(img_base); |
626 | module->entry = get_entry_point(img_base); |
627 | module->refcount = 1; |
627 | module->refcount = 1; |
628 | 628 | ||
629 | dos = (PIMAGE_DOS_HEADER)img_base; |
629 | dos = (PIMAGE_DOS_HEADER)img_base; |
630 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
630 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
631 | exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base, |
631 | exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base, |
632 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
632 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
633 | 633 | ||
634 | module->end = MakePtr(uint32_t,img_base, nt->OptionalHeader.SizeOfImage); |
634 | module->end = MakePtr(uint32_t,img_base, nt->OptionalHeader.SizeOfImage); |
635 | 635 | ||
636 | module->img_hdr = nt; |
636 | module->img_hdr = nt; |
637 | module->img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); |
637 | module->img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); |
638 | module->img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base, |
638 | module->img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base, |
639 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
639 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
640 | 640 | ||
641 | list_add_tail(&module->list, &dll_list); |
641 | list_add_tail(&module->list, &dll_list); |
642 | 642 | ||
643 | if( link_image(img_base)) |
643 | if( link_image(img_base)) |
644 | return module; |
644 | return module; |
645 | return NULL; |
645 | return NULL; |
646 | }; |
646 | }; |
647 | 647 | ||
648 | return NULL; |
648 | return NULL; |
649 | };=>>>>>>>=>> |
649 | };=>>>>>>>=>> |