Rev 6767 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6767 | Rev 6810 | ||
---|---|---|---|
Line 13... | Line 13... | ||
13 | cmp byte [esi], 'M' |
13 | cmp byte [esi], 'M' |
14 | jz .parse_mz |
14 | jz .parse_mz |
15 | cmp [esi+STRIPPED_PE_HEADER.NumberOfRvaAndSizes], SPE_DIRECTORY_EXPORT |
15 | cmp [esi+STRIPPED_PE_HEADER.NumberOfRvaAndSizes], SPE_DIRECTORY_EXPORT |
16 | jbe @f |
16 | jbe @f |
17 | mov edx, [esi+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.VirtualAddress] |
17 | mov edx, [esi+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.VirtualAddress] |
- | 18 | mov edx, [esi+edx+IMAGE_EXPORT_DIRECTORY.TimeDateStamp] |
|
18 | @@: |
19 | @@: |
19 | mov [eax+MODULE.timestamp], edx |
20 | mov [eax+MODULE.timestamp], edx |
20 | mov edx, esi |
21 | mov edx, esi |
21 | sub edx, [esi+STRIPPED_PE_HEADER.ImageBase] |
22 | sub edx, [esi+STRIPPED_PE_HEADER.ImageBase] |
22 | mov [eax+MODULE.basedelta], edx |
23 | mov [eax+MODULE.basedelta], edx |
Line 115... | Line 116... | ||
115 | jbe .pagedone |
116 | jbe .pagedone |
116 | push esi |
117 | push esi |
117 | fpo_delta = fpo_delta + 4 |
118 | fpo_delta = fpo_delta + 4 |
118 | ; 2c. Check whether we have mprotect-ed the current page at the previous step. |
119 | ; 2c. Check whether we have mprotect-ed the current page at the previous step. |
119 | ; If so, go to 2e. |
120 | ; If so, go to 2e. |
- | 121 | add edx, esi |
|
120 | cmp [.next_page_addr+fpo_delta], edx |
122 | cmp [.next_page_addr+fpo_delta], edx |
121 | jz .mprotected_earlier |
123 | jz .mprotected_earlier |
122 | ; 2d. We are going to modify data, so mprotect the current page to be writable. |
124 | ; 2d. We are going to modify data, so mprotect the current page to be writable. |
123 | ; Save the old protection, we will restore it after the block is processed. |
125 | ; Save the old protection, we will restore it after the block is processed. |
124 | ; Ignore any error. |
126 | ; Ignore any error. |
Line 128... | Line 130... | ||
128 | PROT_EXEC = 4 |
130 | PROT_EXEC = 4 |
129 | push ecx |
131 | push ecx |
130 | mov eax, 68 |
132 | mov eax, 68 |
131 | mov ebx, 30 |
133 | mov ebx, 30 |
132 | mov ecx, PROT_READ+PROT_WRITE |
134 | mov ecx, PROT_READ+PROT_WRITE |
133 | add edx, esi |
- | |
134 | mov esi, 0x1000 |
135 | mov esi, 0x1000 |
135 | call FS_SYSCALL_PTR |
136 | call FS_SYSCALL_PTR |
136 | pop ecx |
137 | pop ecx |
137 | jmp .mprotected |
138 | jmp .mprotected |
138 | ; 2e. We have already mprotect-ed the current page, |
139 | ; 2e. We have already mprotect-ed the current page, |
Line 180... | Line 181... | ||
180 | jmp .relocloop |
181 | jmp .relocloop |
181 | .relocdone: |
182 | .relocdone: |
182 | ; 2i. Restore memory protection changed in 2d. |
183 | ; 2i. Restore memory protection changed in 2d. |
183 | pop ecx |
184 | pop ecx |
184 | fpo_delta = fpo_delta - 4 |
185 | fpo_delta = fpo_delta - 4 |
185 | cmp ecx, -1 |
- | |
186 | jz @f |
- | |
187 | mov eax, 68 |
186 | mov eax, 68 |
188 | mov ebx, 30 |
187 | mov ebx, 30 |
189 | mov esi, 0x1000 |
188 | mov esi, 0x1000 |
190 | call FS_SYSCALL_PTR |
189 | call FS_SYSCALL_PTR |
191 | @@: |
- | |
192 | pop esi |
190 | pop esi |
193 | fpo_delta = fpo_delta - 4 |
191 | fpo_delta = fpo_delta - 4 |
194 | .pagedone: |
192 | .pagedone: |
195 | cmp [.sizeleft+fpo_delta], 0 |
193 | cmp [.sizeleft+fpo_delta], 0 |
196 | jnz .pageloop |
194 | jnz .pageloop |
Line 240... | Line 238... | ||
240 | locals |
238 | locals |
241 | export_base dd ? |
239 | export_base dd ? |
242 | export_ptr dd ? |
240 | export_ptr dd ? |
243 | export_size dd ? |
241 | export_size dd ? |
244 | import_module dd ? |
242 | import_module dd ? |
245 | import_dir dd ? |
- | |
246 | import_descriptor dd ? |
243 | import_descriptor dd ? |
- | 244 | next_forwarder dd ? |
|
- | 245 | bound_import_descriptor dd ? |
|
247 | bound_import_dir dd ? |
246 | bound_import_dir dd ? |
248 | bound_import_cur_module dd ? |
247 | bound_modules_count dd ? |
249 | relocated_bound_modules_count dd ? |
248 | bound_modules_ptr dd ? |
- | 249 | bound_module dd ? |
|
250 | relocated_bound_modules_ptr dd ? |
250 | bound_modules_left dd ? |
251 | cur_page dd -0x1000 ; the page at 0xFFFFF000 is never allocated |
251 | cur_page dd -0x1000 ; the page at 0xFFFFF000 is never allocated |
252 | cur_page_old_access dd ? |
252 | cur_page_old_access dd ? |
253 | next_page dd -1 |
253 | next_page dd -1 |
254 | next_page_old_access dd ? |
254 | next_page_old_access dd ? |
255 | endl |
255 | endl |
Line 279... | Line 279... | ||
279 | ; it is impossible to bind such a binary, but it is still valid. |
279 | ; it is impossible to bind such a binary, but it is still valid. |
280 | ; If OriginalFirstThunk is absent, use FirstThunk as source array. |
280 | ; If OriginalFirstThunk is absent, use FirstThunk as source array. |
281 | mov ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk] |
281 | mov ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk] |
282 | mov ebp, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk] |
282 | mov ebp, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk] |
283 | test ebx, ebx |
283 | test ebx, ebx |
284 | jnz .label1 |
284 | jnz @f |
285 | mov ebx, ebp |
285 | mov ebx, ebp |
286 | .label1: |
286 | @@: |
287 | ; FirstThunk and OriginalFirstThunk are RVAs. |
287 | ; FirstThunk and OriginalFirstThunk are RVAs. |
288 | add ebx, [esi+MODULE.base] |
288 | add ebx, [esi+MODULE.base] |
289 | add ebp, [esi+MODULE.base] |
289 | add ebp, [esi+MODULE.base] |
290 | ; Source array is terminated with zero dword. |
290 | ; Source array is terminated with zero dword. |
291 | .loop: |
291 | .loop: |
Line 343... | Line 343... | ||
343 | ; and forwarded exports. |
343 | ; and forwarded exports. |
344 | ; * New-style bound import: |
344 | ; * New-style bound import: |
345 | ; we have two parallel arrays of import descriptors and bound descriptors, |
345 | ; we have two parallel arrays of import descriptors and bound descriptors, |
346 | ; pointed to by two directories. Timestamp field has a special value -1 |
346 | ; pointed to by two directories. Timestamp field has a special value -1 |
347 | ; in import descriptors, real timestamps are in bound descriptors. |
347 | ; in import descriptors, real timestamps are in bound descriptors. |
348 | ; There can be different strategies; we loop over bound descriptors |
- | |
349 | ; and scan for corresponding import descriptors only if needed, |
- | |
350 | ; this accelerates the fast path where all timestamps are correct and |
- | |
351 | ; dependencies are not relocated. |
- | |
352 | ; * No import: not really different from normal import with no descriptors. |
348 | ; * No import: not really different from normal import with no descriptors. |
- | 349 | ; Forwarded exports are the part where binding goes really interesting. |
|
- | 350 | ; The address of forwarded export can change with any library in the chain. |
|
- | 351 | ; In old-style bound import, a descriptor can list only the library itself, |
|
- | 352 | ; so it is impossible to bind forwarded exports at all; thunks that point to |
|
- | 353 | ; forwarded exports are linked in the list starting from ForwarderChain in import descriptor. |
|
- | 354 | ; New-style bound import exists exactly to address this problem; it allows to |
|
353 | ; There are two large parts in this function: |
355 | ; list several related libraries for one imported module. |
354 | ; step 2 handles unbound and old-style bound import, where we loop over import descriptors; |
356 | ; However, even with new-style bound import, some forwarded exports can |
- | 357 | ; still remain unbound: binding tool can fail to load dependent libraries |
|
- | 358 | ; during binding time; the tool from MS SDK for unknown reason just refuses to |
|
- | 359 | ; bind forwarded exports except for built-in white list if subsystem version is |
|
355 | ; step 3 handles new-style bound import, where we loop over bound descriptors. |
360 | ; < 6.0. So even with new-style bound import, ForwarderChain still can be non-empty. |
- | 361 | ; Thus, we always need to look at old-style import descriptor. |
|
356 | ; 1. Fetch addresses of two directories. We are not interested in their sizes. |
362 | ; 1. Fetch addresses of two directories. We are not interested in their sizes. |
357 | ; ebp = import RVA |
363 | ; ebp = import RVA |
358 | ; ebx = bound import RVA |
364 | ; ebx = bound import RVA |
359 | xor ebx, ebx |
365 | xor ebx, ebx |
360 | xor ebp, ebp |
366 | xor ebp, ebp |
Line 376... | Line 382... | ||
376 | mov ebp, [eax+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT*sizeof.IMAGE_DATA_DIRECTORY] |
382 | mov ebp, [eax+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT*sizeof.IMAGE_DATA_DIRECTORY] |
377 | cmp [eax+IMAGE_NT_HEADERS.OptionalHeader.NumberOfDirectories], IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT |
383 | cmp [eax+IMAGE_NT_HEADERS.OptionalHeader.NumberOfDirectories], IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT |
378 | jbe .common |
384 | jbe .common |
379 | mov ebx, [eax+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT*sizeof.IMAGE_DATA_DIRECTORY] |
385 | mov ebx, [eax+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT*sizeof.IMAGE_DATA_DIRECTORY] |
380 | .common: |
386 | .common: |
381 | mov [import_dir], ebp |
- | |
382 | ; If bound import is present, go to 3. |
- | |
383 | ; If both directories are absent, no import - nothing to do. |
387 | ; If import directory is not present, no import - nothing to do. |
384 | ; Otherwise, advance to 2. |
388 | ; Ignore bound import directory in this case. |
385 | test ebx, ebx |
- | |
386 | jnz .bound_import |
- | |
387 | test ebp, ebp |
389 | test ebp, ebp |
388 | jz .done |
390 | jz .done |
389 | ; 2. Unbound import or old-style bound import. |
- | |
390 | ; Repeat 2a-2h for all descriptors in the directory. |
- | |
391 | add ebp, [esi+MODULE.base] ; directories contain RVA |
391 | add ebp, [esi+MODULE.base] ; directories contain RVA |
- | 392 | add ebx, [esi+MODULE.base] ; directories contain RVA |
|
- | 393 | mov [bound_import_dir], ebx |
|
- | 394 | mov [bound_import_descriptor], ebx |
|
- | 395 | ; Repeat remaining steps for all descriptors in the directory. |
|
392 | .normal_import_loop: |
396 | .descriptor_loop: |
393 | ; 2a. Check whether this descriptor is an end mark with zero fields. |
397 | ; 2. Check whether this descriptor is an end mark with zero fields. |
394 | ; Look at Name field. |
398 | ; Look at Name field. |
395 | mov edi, [ebp+IMAGE_IMPORT_DESCRIPTOR.Name] |
399 | mov edi, [ebp+IMAGE_IMPORT_DESCRIPTOR.Name] |
396 | test edi, edi |
400 | test edi, edi |
397 | jz .done |
401 | jz .done |
398 | ; 2b. Load the target module. |
402 | ; 3. Load the target module. |
399 | add edi, [esi+MODULE.base] ; Name field is RVA |
403 | add edi, [esi+MODULE.base] ; Name field is RVA |
400 | call load_imported_module ; should preserve esi,ebp |
404 | call load_imported_module ; should preserve esi,ebp |
401 | test eax, eax |
405 | test eax, eax |
402 | jz .failed |
406 | jz .failed |
403 | mov [import_module], eax |
407 | mov [import_module], eax |
404 | ; 2c. Check whether the descriptor has a non-stale old-style binding. |
408 | ; 4. Check whether the descriptor has a non-stale old-style binding. |
405 | ; Zero timestamp means "not bound". |
409 | ; Zero timestamp means "not bound". |
- | 410 | ; Timestamp 0xFFFFFFFF means "new-style binding". |
|
406 | ; Mismatched timestamp means "stale binding". |
411 | ; Mismatched timestamp means "stale binding". |
407 | ; In both cases, go to 2g. |
412 | ; In first and third cases, go to 9. |
- | 413 | ; In second case, go to 10 for further checks. |
|
408 | mov edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.TimeDateStamp] |
414 | mov edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.TimeDateStamp] |
409 | test edx, edx |
415 | test edx, edx |
410 | jz .resolve_normal_import |
416 | jz .resolve_generic |
- | 417 | cmp edx, -1 |
|
- | 418 | jz .new_binding |
|
411 | cmp edx, [eax+MODULE.timestamp] |
419 | cmp edx, [eax+MODULE.timestamp] |
412 | jnz .resolve_normal_import |
420 | jnz .resolve_generic |
413 | ; 2d. The descriptor has a non-stale old-style binding. |
421 | ; 5. The descriptor has a non-stale old-style binding. |
414 | ; There are two cases when we still need to do something: |
422 | ; There are two cases when we still need to do something: |
415 | ; * if the target module has been relocated, we need to add |
423 | ; * if the target module has been relocated, we need to add |
416 | ; relocation delta to all addresses; |
424 | ; relocation delta to all addresses; |
417 | ; * if some exports are forwarded, old-style binding cannot bind them: |
425 | ; * if some exports are forwarded, we need to resolve them. |
418 | ; there is only one timestamp field, we can't verify timestamps |
- | |
419 | ; of forward targets. |
- | |
420 | ; Thunks for forwarded exports contain index of next forwarded export |
426 | ; Thunks for forwarded exports contain index of next forwarded export |
421 | ; instead of target address, making a single-linked list terminated by -1. |
427 | ; instead of target address, making a single-linked list terminated by -1. |
422 | ; ForwarderChain is the head of the list. |
428 | ; ForwarderChain is the head of the list. |
423 | ; If both problems are present, we resort to 2g as if binding is stale, |
429 | ; Check for the first problem first; the corresponding code can handle both. |
424 | ; it shouldn't be encountered normally anyway: relocations should be avoided, |
- | |
425 | ; and forwarded exports should be new-style bound. |
- | |
426 | ; If the target module is not relocated, go to 2f. |
430 | ; If the target module is relocated, go to 8. |
427 | ; If the target module is relocated and there are no forwarded exports, |
431 | ; If the target module is not relocated, but has forwarded exports, go to 7. |
428 | ; advance to 2e. |
432 | ; Otherwise, advance to 6. |
- | 433 | .old_binding: |
|
429 | cmp [eax+MODULE.basedelta], 0 |
434 | cmp [eax+MODULE.basedelta], 0 |
430 | jz .normal_import_check_forwarders |
435 | jnz .old_binding_relocate |
- | 436 | .check_forwarder_chain: |
|
431 | cmp [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain], -1 |
437 | cmp [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain], -1 |
432 | jnz .resolve_normal_import |
438 | jnz .resolve_forward_chain |
433 | ; 2e. Binding is correct, but we need to add MODULE.basedelta |
- | |
434 | ; to all imported addresses in FirstThunk array. |
- | |
435 | ; For consistency with generic-case resolve_import_from_module, |
- | |
436 | ; check for end of thunks by looking at OriginalFirstThunk array. |
- | |
437 | ; After that, go to 2h. |
439 | .next_descriptor: |
438 | mov edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk] |
- | |
439 | add edx, [esi+MODULE.base] |
440 | ; 6. Advance to next descriptor and continue the loop. |
440 | mov ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk] |
441 | add ebp, sizeof.IMAGE_IMPORT_DESCRIPTOR |
441 | add ebx, [esi+MODULE.base] |
- | |
442 | mov edi, [eax+MODULE.basedelta] |
- | |
443 | .normal_import_add_delta: |
- | |
444 | cmp dword [ebx], 0 |
- | |
445 | jz .normal_import_next |
442 | jmp .descriptor_loop |
446 | call .ensure_writable ; should preserve esi,edi,ebp,ebx,edx |
- | |
447 | add dword [edx], edi |
- | |
448 | add edx, 4 |
- | |
449 | add ebx, 4 |
- | |
450 | jmp .normal_import_add_delta |
- | |
451 | .normal_import_check_forwarders: |
443 | .resolve_forward_chain: |
452 | ; 2f. The target module is not relocated. |
- | |
453 | ; Exports that are not forwarded are correct. |
444 | ; 7. Resolve all thunks from ForwarderChain list. |
454 | ; Go through ForwarderChain list and resolve all exports from it. |
- | |
455 | ; After that, go to 2h. |
- | |
456 | mov edi, [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain] |
- | |
457 | cmp edi, -1 |
- | |
458 | jz .normal_import_next ; don't prepare_import_from_module for empty list |
- | |
459 | mov eax, [import_module] |
445 | mov eax, [import_module] |
460 | mov eax, [eax+MODULE.base] |
446 | mov eax, [eax+MODULE.base] |
461 | call prepare_import_from_module |
447 | call prepare_import_from_module |
- | 448 | mov edi, [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain] |
|
462 | .normal_import_forward_chain: |
449 | .resolve_forward_chain_loop: |
463 | mov ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk] |
450 | mov ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk] |
464 | add ebx, [esi+MODULE.base] |
451 | add ebx, [esi+MODULE.base] |
465 | mov ecx, [ebx+edi*4] |
452 | mov ecx, [ebx+edi*4] |
466 | get_address_for_thunk ; should preserve esi,edi,ebp |
453 | get_address_for_thunk ; should preserve esi,edi,ebp |
467 | test eax, eax |
454 | test eax, eax |
Line 472... | Line 459... | ||
472 | lea edx, [edx+edi*4] |
459 | lea edx, [edx+edi*4] |
473 | call .ensure_writable ; should preserve edx,ebx,esi,ebp |
460 | call .ensure_writable ; should preserve edx,ebx,esi,ebp |
474 | mov edi, [edx] ; next forwarded export |
461 | mov edi, [edx] ; next forwarded export |
475 | mov [edx], ebx ; store the address |
462 | mov [edx], ebx ; store the address |
476 | cmp edi, -1 |
463 | cmp edi, -1 |
477 | jnz .normal_import_forward_chain |
464 | jnz .resolve_forward_chain_loop |
- | 465 | ; After resolving, we are done with this import descriptor, go to 6. |
|
- | 466 | jmp .next_descriptor |
|
- | 467 | .done: |
|
- | 468 | call .restore_protection |
|
- | 469 | xor eax, eax |
|
- | 470 | ret |
|
- | 471 | .old_binding_relocate: |
|
- | 472 | ; 8. The descriptor has a non-stale old-style binding, |
|
- | 473 | ; but the target module is relocated, so we need to add MODULE.basedelta to |
|
- | 474 | ; all addresses. Also, there can be forwarded exports. |
|
- | 475 | ; For consistency with generic-case resolve_import_from_module, |
|
- | 476 | ; check for end of thunks by looking at OriginalFirstThunk array. |
|
- | 477 | ; Note: we assume here that ForwarderChain list is ordered. |
|
- | 478 | ; After that, go to 6. |
|
- | 479 | mov edi, [eax+MODULE.basedelta] |
|
- | 480 | cmp [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain], -1 |
|
- | 481 | jz @f |
|
- | 482 | mov eax, [import_module] |
|
- | 483 | mov eax, [eax+MODULE.base] |
|
- | 484 | call prepare_import_from_module |
|
- | 485 | @@: |
|
- | 486 | mov edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk] |
|
- | 487 | add edx, [esi+MODULE.base] |
|
- | 488 | mov ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk] |
|
- | 489 | add ebx, [esi+MODULE.base] |
|
- | 490 | mov eax, [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain] |
|
- | 491 | lea eax, [edx+eax*4] |
|
- | 492 | mov [next_forwarder], eax |
|
- | 493 | .old_binding_relocate_loop: |
|
- | 494 | cmp dword [ebx], 0 |
|
- | 495 | jz .next_descriptor |
|
- | 496 | call .ensure_writable ; should preserve esi,edi,ebp,ebx,edx |
|
- | 497 | cmp edx, [next_forwarder] |
|
- | 498 | jz .old_binding_relocate_forwarder |
|
- | 499 | add dword [edx], edi |
|
- | 500 | .old_binding_relocate_next: |
|
- | 501 | add edx, 4 |
|
- | 502 | add ebx, 4 |
|
- | 503 | jmp .old_binding_relocate_loop |
|
- | 504 | .old_binding_relocate_forwarder: |
|
- | 505 | mov ecx, [ebx] |
|
- | 506 | get_address_for_thunk |
|
- | 507 | test eax, eax |
|
- | 508 | jz .failed |
|
- | 509 | mov edx, [next_forwarder] |
|
- | 510 | mov ecx, [edx] |
|
- | 511 | mov [edx], eax |
|
- | 512 | mov eax, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk] |
|
- | 513 | add eax, [esi+MODULE.base] |
|
- | 514 | lea eax, [eax+ecx*4] |
|
- | 515 | mov [next_forwarder], eax |
|
478 | jmp .normal_import_next |
516 | jmp .old_binding_relocate_next |
479 | .resolve_normal_import: |
517 | .resolve_generic: |
480 | ; 2g. Run generic-case resolver. |
518 | ; 9. Run generic-case resolver. |
481 | mov [import_descriptor], ebp |
519 | mov [import_descriptor], ebp |
482 | resolve_import_from_module .failed ; should preserve esi |
520 | resolve_import_from_module .failed ; should preserve esi |
483 | mov ebp, [import_descriptor] |
521 | mov ebp, [import_descriptor] |
484 | .normal_import_next: |
522 | ; After that, go to 6. |
485 | ; 2h. Advance to next descriptor and continue the loop. |
- | |
486 | add ebp, sizeof.IMAGE_IMPORT_DESCRIPTOR |
- | |
487 | jmp .normal_import_loop |
523 | jmp .next_descriptor |
488 | .bound_import: |
524 | .new_binding: |
489 | ; 3. New-style bound import. |
525 | ; New-style bound import. |
- | 526 | ; 10. Locate the new-style descriptor corresponding to the current |
|
- | 527 | ; import descriptor. |
|
- | 528 | ; 10a. Check the current new-style descriptor: the one that follows |
|
- | 529 | ; previous one, if there was the previous one, or the first one. |
|
490 | ; Repeat 3a-3o for all descriptors in bound import directory. |
530 | ; In most cases, new-style descriptors are in the same order as |
- | 531 | ; import descriptors, so full loop in 10b can be avoided. |
|
491 | mov [bound_import_dir], ebx |
532 | mov edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.Name] |
492 | add ebx, [esi+MODULE.base] |
533 | add edx, [esi+MODULE.base] |
493 | .bound_import_loop: |
534 | mov ebx, [bound_import_descriptor] |
494 | ; 3a. Check whether this descriptor is an end mark with zero fields. |
- | |
495 | movzx edi, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName] |
535 | movzx edi, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName] |
496 | mov [bound_import_cur_module], edi |
- | |
497 | test edi, edi |
536 | test edi, edi |
- | 537 | jz .look_new_binding_hard |
|
- | 538 | add edi, [bound_import_dir] |
|
- | 539 | xor ecx, ecx |
|
- | 540 | @@: |
|
- | 541 | mov al, [edx+ecx] |
|
- | 542 | cmp al, [edi+ecx] |
|
- | 543 | jnz .look_new_binding_hard |
|
- | 544 | test al, al |
|
- | 545 | jz .new_binding_found |
|
- | 546 | inc ecx |
|
498 | jz .done |
547 | jmp @b |
- | 548 | .look_new_binding_hard: |
|
- | 549 | ; 10b. We are out of luck with the current new-style descriptor, |
|
- | 550 | ; so loop over all of them looking for the matching one. |
|
- | 551 | mov ebx, [bound_import_dir] |
|
- | 552 | .look_new_binding_loop: |
|
- | 553 | movzx edi, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName] |
|
- | 554 | add edi, [bound_import_dir] |
|
- | 555 | xor ecx, ecx |
|
- | 556 | @@: |
|
- | 557 | mov al, [edx+ecx] |
|
- | 558 | cmp al, [edi+ecx] |
|
- | 559 | jnz .look_new_binding_next |
|
- | 560 | test al, al |
|
- | 561 | jz .new_binding_found |
|
- | 562 | inc ecx |
|
- | 563 | jmp @b |
|
- | 564 | .look_new_binding_next: |
|
- | 565 | movzx ecx, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.NumberOfModuleForwarderRefs] |
|
- | 566 | lea ebx, [ebx+(ecx+1)*sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR] |
|
- | 567 | jmp .look_new_binding_loop |
|
- | 568 | .new_binding_found: |
|
- | 569 | ; 10c. Store the next descriptor for subsequent scans. |
|
- | 570 | movzx ecx, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.NumberOfModuleForwarderRefs] |
|
- | 571 | lea eax, [ebx+(ecx+1)*sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR] |
|
- | 572 | mov [bound_import_descriptor], eax |
|
499 | ; Bound import descriptors come in groups. |
573 | ; Bound import descriptors come in groups. |
500 | ; The first descriptor in each group corresponds to the main imported module. |
574 | ; The first descriptor in each group corresponds to the main imported module. |
501 | ; If some exports from the module are forwarded, additional descriptors |
575 | ; If some exports from the module are forwarded, additional descriptors |
502 | ; are created for modules where those exports are forwarded to. |
576 | ; are created for modules where those exports are forwarded to. |
503 | ; Number of additional descriptors is given by one field in the first descriptor. |
577 | ; Number of additional descriptors is given by one field in the first descriptor. |
504 | ; 3b. Prepare for loop at 3c-3f with loading targets of all exports. |
578 | ; 11. We have already loaded the main module, validate its timestamp. |
505 | ; This includes the target module and all modules in chains of forwarded exports. |
579 | ; If timestamp does not match, go to 9 to run generic-case resolver. |
- | 580 | mov eax, [import_module] |
|
- | 581 | mov edx, [eax+MODULE.timestamp] |
|
506 | movzx ebp, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.NumberOfModuleForwarderRefs] |
582 | cmp edx, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.TimeDateStamp] |
507 | mov [relocated_bound_modules_count], 0 |
583 | jnz .resolve_generic |
- | 584 | ; 12. If there are no additional libraries, |
|
- | 585 | ; the situation is exactly same as old-style binding, so go to 5. |
|
- | 586 | test ecx, ecx |
|
- | 587 | jz .old_binding |
|
- | 588 | ; 13. Load additional libraries and validate their timestamps. |
|
- | 589 | ; If at least one timestamp is invalid, resort to generic-case resolving. |
|
- | 590 | ; 13a. Allocate memory for all bound modules, including the main module. |
|
- | 591 | lea ecx, [(ecx+1)*4] |
|
- | 592 | stdcall malloc, ecx |
|
- | 593 | test eax, eax |
|
- | 594 | jz .failed |
|
508 | mov [relocated_bound_modules_ptr], 0 |
595 | mov [bound_modules_ptr], eax |
- | 596 | ; 13b. Store the main module. |
|
509 | mov [import_module], 0 |
597 | mov edx, [import_module] |
510 | .bound_import_forwarder_loop: |
598 | mov [eax], edx |
511 | ; 3c. Load a referenced module. |
599 | xor ecx, ecx |
512 | ; Names in bound import descriptors are relative to bound import directory, |
600 | ; 13c. Loop over all additional descriptors. |
- | 601 | .newstyle_load_loop: |
|
513 | ; not RVAs. |
602 | inc ecx |
- | 603 | mov [bound_modules_count], ecx |
|
- | 604 | movzx edi, [ebx+ecx*sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR+IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName] |
|
514 | add edi, [bound_import_dir] |
605 | add edi, [bound_import_dir] |
515 | call load_imported_module ; should preserve ebx,esi,ebp |
606 | call load_imported_module ; should preserve ebx,esi,ebp |
516 | test eax, eax |
607 | test eax, eax |
517 | jz .bound_import_failed |
608 | jz .newstyle_failed |
518 | ; The target module is first in the list. |
609 | mov ecx, [bound_modules_count] |
- | 610 | mov edx, [ebx+ecx*sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR+IMAGE_BOUND_IMPORT_DESCRIPTOR.TimeDateStamp] |
|
519 | cmp [import_module], 0 |
611 | cmp [eax+MODULE.timestamp], edx |
520 | jnz @f |
612 | jnz .newstyle_stale |
521 | mov [import_module], eax |
613 | mov edx, [bound_modules_ptr] |
522 | @@: |
- | |
523 | ; 3d. Check whether timestamp in the descriptor matches module timestamp. |
614 | mov [edx+ecx*4], eax |
524 | ; If not, go to 3h which after some preparations will resort to generic-case |
615 | cmp cx, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.NumberOfModuleForwarderRefs] |
525 | ; resolve_import_from_module; in this case, we stop processing the group, |
- | |
526 | ; resolve_import_from_module will take care about additional modules anyway. |
- | |
527 | mov edx, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.TimeDateStamp] |
616 | jb .newstyle_load_loop |
528 | test edx, edx |
617 | inc ecx |
529 | jz .bound_import_wrong_timestamp |
618 | mov [bound_modules_count], ecx |
530 | cmp edx, [eax+MODULE.timestamp] |
619 | ; New-style binding has correct timestamp. |
531 | jnz .bound_import_wrong_timestamp |
620 | ; There still can be same two problems as in step 5 with old-style binding. |
532 | ; 3e. Collect all referenced modules that have been relocated. |
621 | ; 14. Check whether at least one module is relocated. If so, go to 16. |
- | 622 | .newstyle_check_reloc: |
|
- | 623 | mov eax, [edx] |
|
533 | cmp [eax+MODULE.basedelta], 0 |
624 | cmp [eax+MODULE.basedelta], 0 |
534 | jz .bound_import_forwarder_next |
- | |
535 | mov edi, eax |
- | |
536 | ; We don't want to reallocate too often, since reallocation |
- | |
537 | ; may involve copying our data to a new place. |
- | |
538 | ; We always reserve space that is a power of two; in this way, |
- | |
539 | ; the wasted space is never greater than the used space, |
- | |
540 | ; and total time of copying the data is O(number of modules). |
- | |
541 | mov eax, [relocated_bound_modules_ptr] |
- | |
542 | mov edx, [relocated_bound_modules_count] |
- | |
543 | ; X is a power of two or zero if and only if (X and (X - 1)) is zero |
- | |
544 | lea ecx, [edx-1] |
- | |
545 | test ecx, edx |
- | |
546 | jnz .bound_import_norealloc |
625 | jnz .newstyle_need_reloc |
547 | ; if the current size is zero, allocate 1 item, |
- | |
548 | ; otherwise double number of items. |
- | |
549 | ; Item size is 4 bytes. |
- | |
550 | lea edx, [edx*8] |
- | |
551 | test edx, edx |
- | |
552 | jnz @f |
- | |
553 | mov edx, 4 |
626 | add edx, 4 |
554 | @@: |
- | |
555 | stdcall realloc, [relocated_bound_modules_ptr], edx |
- | |
556 | test eax, eax |
- | |
557 | jz .bound_import_failed |
- | |
558 | mov [relocated_bound_modules_ptr], eax |
- | |
559 | .bound_import_norealloc: |
- | |
560 | mov edx, [relocated_bound_modules_count] |
- | |
561 | inc [relocated_bound_modules_count] |
- | |
562 | mov [eax+edx*4], edi |
- | |
563 | .bound_import_forwarder_next: |
- | |
564 | ; 3f. Advance to the next descriptor in the group. |
- | |
565 | add ebx, sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR |
- | |
566 | movzx edi, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName] |
- | |
567 | dec ebp |
627 | dec ecx |
568 | jns .bound_import_forwarder_loop |
628 | jnz .newstyle_check_reloc |
569 | ; 3g. All timestamps are correct. |
629 | ; 15. Bound modules are not relocated. |
570 | ; If all targets are not relocated, then we have nothing to do |
630 | ; The only remaining problem could be unbound forwarders. |
571 | ; with exports from the current module, so continue loop at 3a; |
631 | ; Free memory allocated at 13a and let steps 6 and 7 do their work. |
572 | ; ebx already points to the next descriptor. |
- | |
573 | ; Otherwise, go to 3i. |
- | |
574 | cmp [relocated_bound_modules_count], 0 |
632 | stdcall free, [bound_modules_ptr] |
575 | jz .bound_import_loop |
- | |
576 | jmp .bound_import_fix |
633 | jmp .check_forwarder_chain |
577 | .bound_import_wrong_timestamp: |
- | |
578 | ; 3h. We have aborted the loop over the group; |
- | |
579 | ; advance ebx so that it points to the first descriptor of the next group, |
- | |
580 | ; make a mark so that 3l will know that we need to reimport everything. |
- | |
581 | ; We don't need [relocated_bound_modules_count] in this case anymore, |
- | |
582 | ; use zero value as a mark. |
- | |
583 | lea ebx, [ebx+(ebp+1)*sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR] |
- | |
584 | mov [relocated_bound_modules_count], 0 |
- | |
585 | .bound_import_fix: |
634 | .newstyle_stale: |
586 | ; 3i. We need to do something with exported addresses. |
- | |
587 | ; Find corresponding import descriptors; there can be more than one. |
- | |
588 | ; Repeat 3j-3n for all import descriptors. |
- | |
589 | mov ebp, [import_dir] |
- | |
590 | add ebp, [esi+MODULE.base] |
- | |
591 | .look_related_descriptors: |
- | |
592 | ; 3j. Check whether we have reached end of import table. |
- | |
593 | ; If so, go to 3o. |
- | |
594 | mov edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.Name] |
- | |
595 | test edx, edx |
- | |
596 | jz .bound_import_next |
- | |
597 | ; 3k. Check whether the current import descriptor matches the current |
- | |
598 | ; bound import descriptor. Check Name fields. |
- | |
599 | ; If so, advance to 3l. |
- | |
600 | ; Otherwise, advance to the next import descriptor and return to 3j. |
- | |
601 | add edx, [esi+MODULE.base] |
- | |
602 | mov edi, [bound_import_cur_module] |
635 | stdcall free, [bound_modules_ptr] |
603 | @@: |
- | |
604 | mov al, [edx] |
- | |
605 | cmp [edi], al |
- | |
606 | jnz .next_related_descriptor |
- | |
607 | test al, al |
- | |
608 | jz .found_related_descriptor |
- | |
609 | inc edx |
- | |
610 | inc edi |
- | |
611 | jmp @b |
- | |
612 | .next_related_descriptor_restore: |
- | |
613 | mov ebp, [import_descriptor] |
- | |
614 | .next_related_descriptor: |
- | |
615 | add ebp, sizeof.IMAGE_IMPORT_DESCRIPTOR |
- | |
616 | jmp .look_related_descriptors |
636 | jmp .resolve_generic |
617 | .found_related_descriptor: |
- | |
618 | ; 3l. Check what we should do: |
- | |
619 | ; advance to 3m, if we need to reimport everything, |
637 | ; 16. The descriptor has a non-stale new-style binding, |
620 | ; go to 3n, if we just need to relocate something. |
638 | ; but at least one of target modules is relocated, so we need to add |
621 | mov [import_descriptor], ebp |
- | |
622 | cmp [relocated_bound_modules_count], 0 |
- | |
623 | jnz .bound_import_add_delta |
- | |
624 | ; 3m. Apply resolve_import_from_module and return to 3j. |
639 | ; MODULE.basedelta to addresses from relocated modules. |
625 | resolve_import_from_module .bound_import_failed ; should preserve ebx,esi |
- | |
626 | jmp .next_related_descriptor_restore |
- | |
627 | .bound_import_add_delta: |
- | |
628 | ; 3n. Loop over all imported symbols. |
640 | ; Also, there can be forwarded exports. |
629 | ; For every imported symbol, check whether it fits within one of relocated |
- | |
630 | ; modules, and if so, apply relocation to it. |
- | |
631 | ; For consistency with generic-case resolve_import_from_module, |
641 | ; For consistency with generic-case resolve_import_from_module, |
632 | ; determine end of thunks from OriginalFirstThunk array. |
642 | ; check for end of thunks by looking at OriginalFirstThunk array. |
- | 643 | ; Note: we assume here that ForwarderChain list is ordered. |
|
- | 644 | ; After that, go to 6. |
|
- | 645 | .newstyle_need_reloc: |
|
- | 646 | mov eax, [import_module] |
|
- | 647 | mov eax, [eax+MODULE.base] |
|
- | 648 | call prepare_import_from_module |
|
633 | mov edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk] |
649 | mov edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk] |
634 | add edx, [esi+MODULE.base] |
650 | add edx, [esi+MODULE.base] |
635 | mov ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk] |
651 | mov ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk] |
636 | add ebx, [esi+MODULE.base] |
652 | add ebx, [esi+MODULE.base] |
- | 653 | mov eax, [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain] |
|
- | 654 | lea eax, [edx+eax*4] |
|
- | 655 | mov [next_forwarder], eax |
|
637 | .bound_import_add_delta_loop: |
656 | .new_binding_relocate_loop: |
638 | cmp dword [ebx], 0 |
657 | cmp dword [ebx], 0 |
639 | jz .next_related_descriptor_restore |
658 | jz .new_binding_relocate_done |
- | 659 | cmp edx, [next_forwarder] |
|
- | 660 | jz .new_binding_resolve_thunk |
|
640 | mov ecx, [relocated_bound_modules_ptr] |
661 | mov [bound_module], 0 |
641 | mov ebp, [relocated_bound_modules_count] |
662 | mov eax, [bound_modules_count] |
- | 663 | mov [bound_modules_left], eax |
|
642 | push esi |
664 | mov edi, [bound_modules_ptr] |
- | 665 | ; There should be at least one module containing address [edx]. |
|
- | 666 | ; There can be more than one if preferred address ranges for two modules intersect; |
|
- | 667 | ; in this case, we are forced to resolve address from scratch. |
|
643 | .find_delta_module: |
668 | .new_binding_lookup_module: |
644 | mov esi, [ecx] |
669 | mov ecx, [edx] |
645 | mov eax, [edx] |
670 | mov eax, [edi] |
646 | sub eax, [esi+MODULE.base] |
671 | sub ecx, [eax+MODULE.base] |
647 | add eax, [esi+MODULE.basedelta] |
672 | add ecx, [eax+MODULE.basedelta] |
648 | cmp eax, [esi+MODULE.size] |
673 | cmp ecx, [eax+MODULE.size] |
- | 674 | jae @f |
|
649 | jb .found_delta_module |
675 | cmp [bound_module], 0 |
- | 676 | jnz .new_binding_resolve_thunk |
|
- | 677 | mov [bound_module], eax |
|
- | 678 | @@: |
|
650 | add ecx, 4 |
679 | add edi, 4 |
651 | dec ebp |
680 | dec [bound_modules_left] |
652 | jnz .find_delta_module |
681 | jnz .new_binding_lookup_module |
- | 682 | mov edi, [bound_module] |
|
- | 683 | mov edi, [edi+MODULE.basedelta] |
|
653 | pop esi |
684 | test edi, edi |
654 | .bound_import_add_delta_next: |
685 | jz .new_binding_relocate_next |
- | 686 | call .ensure_writable ; should preserve esi,edi,ebp,ebx,edx |
|
655 | add ebx, 4 |
687 | add dword [edx], edi |
- | 688 | .new_binding_relocate_next: |
|
656 | add edx, 4 |
689 | add edx, 4 |
- | 690 | add ebx, 4 |
|
657 | jmp .bound_import_add_delta_loop |
691 | jmp .new_binding_relocate_loop |
658 | .found_delta_module: |
692 | .new_binding_resolve_thunk: |
659 | mov ebp, [esi+MODULE.basedelta] |
693 | mov [bound_modules_left], edx |
- | 694 | call .ensure_writable |
|
660 | pop esi |
695 | mov ecx, [ebx] |
661 | call .ensure_writable ; should preserve esi,ebp,ebx,edx |
696 | get_address_for_thunk |
662 | add [edx], ebp |
697 | test eax, eax |
- | 698 | jz .newstyle_failed |
|
663 | jmp .bound_import_add_delta_next |
699 | mov edx, [bound_modules_left] |
664 | .bound_import_next: |
700 | mov ecx, [edx] |
665 | ; 3o. Free the data we might have allocated and return to 3a. |
701 | mov [edx], eax |
666 | cmp [relocated_bound_modules_ptr], 0 |
702 | cmp edx, [next_forwarder] |
667 | jz .bound_import_loop |
703 | jnz .new_binding_relocate_next |
668 | stdcall free, [relocated_bound_modules_ptr] |
704 | mov eax, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk] |
669 | jmp .bound_import_loop |
705 | add eax, [esi+MODULE.base] |
670 | .done: |
- | |
671 | call .restore_protection |
706 | lea eax, [eax+ecx*4] |
672 | xor eax, eax |
707 | mov [next_forwarder], eax |
673 | ret |
708 | jmp .new_binding_relocate_next |
674 | .bound_import_failed: |
709 | .new_binding_relocate_done: |
675 | cmp [relocated_bound_modules_ptr], 0 |
710 | stdcall free, [bound_modules_ptr] |
676 | jz .failed |
711 | jmp .next_descriptor |
- | 712 | .newstyle_failed: |
|
677 | stdcall free, [relocated_bound_modules_ptr] |
713 | stdcall free, [bound_modules_ptr] |
678 | .failed: |
714 | .failed: |
679 | call .restore_protection |
715 | call .restore_protection |
680 | xor eax, eax |
716 | xor eax, eax |
681 | dec eax |
717 | dec eax |
682 | ret |
718 | ret |
Line 795... | Line 831... | ||
795 | cmp byte [eax], 'M' |
831 | cmp byte [eax], 'M' |
796 | jz .parse_mz |
832 | jz .parse_mz |
797 | cmp [eax+STRIPPED_PE_HEADER.NumberOfRvaAndSizes], SPE_DIRECTORY_EXPORT |
833 | cmp [eax+STRIPPED_PE_HEADER.NumberOfRvaAndSizes], SPE_DIRECTORY_EXPORT |
798 | jbe .noexport |
834 | jbe .noexport |
799 | mov edx, [eax+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.VirtualAddress] |
835 | mov edx, [eax+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.VirtualAddress] |
- | 836 | test edx, edx |
|
- | 837 | jz .noexport |
|
800 | add edx, eax |
838 | add edx, eax |
801 | mov [export_ptr], edx |
839 | mov [export_ptr], edx |
802 | mov edx, [eax+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.isize] |
840 | mov edx, [eax+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.isize] |
803 | mov [export_size], edx |
841 | mov [export_size], edx |
804 | ret |
842 | ret |
Line 806... | Line 844... | ||
806 | mov ecx, [eax+3Ch] |
844 | mov ecx, [eax+3Ch] |
807 | add ecx, eax |
845 | add ecx, eax |
808 | cmp [ecx+IMAGE_NT_HEADERS.OptionalHeader.NumberOfDirectories], IMAGE_DIRECTORY_ENTRY_EXPORT |
846 | cmp [ecx+IMAGE_NT_HEADERS.OptionalHeader.NumberOfDirectories], IMAGE_DIRECTORY_ENTRY_EXPORT |
809 | jbe .noexport |
847 | jbe .noexport |
810 | mov edx, [ecx+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddress+IMAGE_DIRECTORY_ENTRY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY] |
848 | mov edx, [ecx+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddress+IMAGE_DIRECTORY_ENTRY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY] |
- | 849 | test edx, edx |
|
- | 850 | jz .noexport |
|
811 | add edx, eax |
851 | add edx, eax |
812 | mov [export_ptr], edx |
852 | mov [export_ptr], edx |
813 | mov edx, [ecx+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.isize+IMAGE_DIRECTORY_ENTRY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY] |
853 | mov edx, [ecx+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.isize+IMAGE_DIRECTORY_ENTRY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY] |
814 | mov [export_size], edx |
854 | mov [export_size], edx |
815 | ret |
855 | ret |
Line 883... | Line 923... | ||
883 | mov edi, [ebx+edx*4] |
923 | mov edi, [ebx+edx*4] |
884 | add edi, [export_base] |
924 | add edi, [export_base] |
885 | push ecx esi |
925 | push ecx esi |
886 | repz cmpsb |
926 | repz cmpsb |
887 | pop esi ecx |
927 | pop esi ecx |
888 | jz .found |
928 | jz .hint_ok |
889 | .ignore_hint: |
929 | .ignore_hint: |
890 | ; 4. Binary search over name table. |
930 | ; 4. Binary search over name table. |
891 | ; Export names are sorted with respect to repz cmpsb. |
931 | ; Export names are sorted with respect to repz cmpsb. |
892 | ; edi <= (the target index) < edx |
932 | ; edi <= (the target index) < edx |
893 | xor edi, edi |
933 | xor edi, edi |
Line 919... | Line 959... | ||
919 | mov edx, eax |
959 | mov edx, eax |
920 | jmp .export_name_search.loop |
960 | jmp .export_name_search.loop |
921 | ; Generic error handler. |
961 | ; Generic error handler. |
922 | .export_name_not_found: |
962 | .export_name_not_found: |
923 | mov ebx, esi |
963 | mov ebx, esi |
924 | mov esi, [module] |
- | |
925 | test esi, esi |
- | |
926 | jnz @f |
- | |
927 | mutex_lock modules_mutex |
- | |
928 | mov ecx, [export_base] |
- | |
929 | call find_module_by_addr |
964 | call .get_module_name |
930 | mutex_unlock modules_mutex |
- | |
931 | @@: |
- | |
932 | mov eax, msg_unknown |
- | |
933 | test esi, esi |
- | |
934 | jz @f |
- | |
935 | mov eax, [esi+MODULE.filename] |
- | |
936 | @@: |
- | |
937 | ccall loader_say_error, msg_export_name_not_found, ebx, msg_export_not_found, eax, 0 |
965 | ccall loader_say_error, msg_export_name_not_found, ebx, msg_export_not_found, eax, 0 |
938 | .return0: |
966 | .return0: |
939 | xor eax, eax |
967 | xor eax, eax |
940 | ret |
968 | ret |
- | 969 | .hint_ok: |
|
- | 970 | mov eax, edx |
|
941 | .found: |
971 | .found: |
942 | ; 5. We have found an index in AddressOfNames/AddressOfNameOrdinals arrays, |
972 | ; 5. We have found an index in AddressOfNames/AddressOfNameOrdinals arrays, |
943 | ; convert it to index in AddressOfFunctions array. |
973 | ; convert it to index in AddressOfFunctions array. |
944 | mov edx, [export_ptr] |
974 | mov edx, [export_ptr] |
945 | mov ebx, [edx+IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals] |
975 | mov ebx, [edx+IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals] |
Line 956... | Line 986... | ||
956 | .check_forwarded: |
986 | .check_forwarded: |
957 | ; This part of code is also used by get_exported_function_by_ordinal. |
987 | ; This part of code is also used by get_exported_function_by_ordinal. |
958 | ; 7. Check whether the address is inside the export directory. |
988 | ; 7. Check whether the address is inside the export directory. |
959 | ; If not, we are done. |
989 | ; If not, we are done. |
960 | add eax, [export_base] |
990 | add eax, [export_base] |
961 | mov esi, eax |
991 | mov ebx, eax |
962 | sub esi, edx |
992 | sub ebx, edx |
963 | cmp esi, [export_size] |
993 | cmp ebx, [export_size] |
964 | jb .export_is_forwarded |
994 | jb .export_is_forwarded |
965 | ret |
995 | ret |
966 | .export_is_forwarded: |
996 | .export_is_forwarded: |
967 | ; The export is forwarded to another module. |
997 | ; The export is forwarded to another module. |
968 | ; The address we have got points to the string " |
998 | ; The address we have got points to the string " |
Line 974... | Line 1004... | ||
974 | inc eax |
1004 | inc eax |
975 | cmp byte [eax-1], '.' |
1005 | cmp byte [eax-1], '.' |
976 | jz .dot_found |
1006 | jz .dot_found |
977 | cmp byte [eax-1], 0 |
1007 | cmp byte [eax-1], 0 |
978 | jnz @b |
1008 | jnz @b |
979 | jmp .export_name_not_found |
1009 | call .get_module_name |
- | 1010 | ccall loader_say_error, msg_invalid_forwarder, eax, 0 |
|
- | 1011 | xor eax, eax |
|
- | 1012 | ret |
|
980 | .dot_found: |
1013 | .dot_found: |
981 | ; 8b. Allocate the memory. |
1014 | ; 8b. Allocate the memory. |
982 | sub eax, ebx |
1015 | sub eax, ebx |
983 | mov edi, eax |
1016 | mov edi, eax |
984 | add eax, 4 ; dll + terminating zero |
1017 | add eax, 4 ; dll + terminating zero |
Line 1055... | Line 1088... | ||
1055 | mutex_unlock modules_mutex |
1088 | mutex_unlock modules_mutex |
1056 | @@: |
1089 | @@: |
1057 | stdcall free, edi |
1090 | stdcall free, edi |
1058 | xor eax, eax |
1091 | xor eax, eax |
1059 | ret |
1092 | ret |
- | 1093 | ||
- | 1094 | fpo_delta = fpo_delta + 4 |
|
- | 1095 | .get_module_name: |
|
- | 1096 | mov esi, [module] |
|
- | 1097 | test esi, esi |
|
- | 1098 | jnz @f |
|
- | 1099 | mutex_lock modules_mutex |
|
- | 1100 | mov ecx, [export_base] |
|
- | 1101 | call find_module_by_addr |
|
- | 1102 | mutex_unlock modules_mutex |
|
- | 1103 | @@: |
|
- | 1104 | mov eax, msg_unknown |
|
- | 1105 | test esi, esi |
|
- | 1106 | jz @f |
|
- | 1107 | mov eax, [esi+MODULE.filename] |
|
- | 1108 | @@: |
|
- | 1109 | retn |
|
1060 | endp |
1110 | endp |
Line 1061... | Line 1111... | ||
1061 | 1111 | ||
1062 | ; Resolve symbol from a module by name. |
1112 | ; Resolve symbol from a module by name. |
1063 | ; prepare_import_from_module should be called beforehand. |
1113 | ; prepare_import_from_module should be called beforehand. |