![]() |
|
|
|
#1
|
|||
|
|||
|
IDA script to fix IAT virtualized/obfuscated by Winlicense/Themida
The each element of IAT obfuscated/virtualized by Themida/Winlicense points to some address of vm code section in run-time.
In older versions of Themida/Winlicense, after goes ahead all arbitrary jmp instructions in this vm code section's context jumped from virtualized IAT, when once ret instruction is executed, the current element value of stack is just final API address. But in newer versions, it is used more complex context which has only arbitrary jmp instructions but also arbitrary call/ret instructions pairs in virtualized code flow. That is, after goes ahead all arbitrary jmp instructions and call/ret pairs in this vm code section's context jumped from virtualized IAT, when final un-paired ret instruction is executed, the current element value of stack points to right Win32 API address. These IDA scripts replace all addresses jumped to vm code section with real Win32 API addresses in IAT virtualized/obfuscated by Themida/Winlicense. In case of x64 executables : Code:
// This IDA script fixes virtualized/obfuscated IAT of x64 executable files packed by Winlicense/Themida
auto dest_addr, api_addr, temp;
auto iat_begin, iat_end;
auto vm_begin, vm_end;
auto fp, ret_event;
auto is_exception;
vm_begin = 0x0; // write starting address of your executable's vm section in here
vm_end = 0x0; // write ending address of your executable's vm section in here
iat_begin = 0x0; // write starting address of your executable's IAT in here
iat_end = 0x0; // write ending address of your executable's IAT in here
fp = fopen("D:\\Your-exe-IAT-fix.log", "w"); // replace your log file name in here
for(dest_addr = iat_begin; dest_addr < iat_end; dest_addr = dest_addr + 8)
{
temp = get_qword(dest_addr);
if(temp >= vm_begin && temp < vm_end)
{
msg("%x : %x : ", dest_addr, temp);
fprintf(fp, "%x : %x : ", dest_addr, temp);
jumpto(temp);
refresh_idaview_anyway();
rip = temp;
api_addr = temp;
while((rip >= vm_begin && rip < vm_end))
{
step_until_ret();
wait_for_next_event(WFNE_SUSP, -1);
if(ret_event == EXCEPTION)
{
is_exception = 1;
break;
}
}
if(is_exception == 1)
break;
api_addr = rip;
patch_qword(dest_addr, api_addr);
msg("fixed : %x : %s\n", api_addr, get_name(api_addr));
fprintf(fp, "fixed : %x : %s\n", api_addr, get_name(api_addr));
}
}
fclose(fp);
msg("Done.\n");
Code:
// This IDA script fixes virtualized/obfuscated IAT of x86 executable files packed by Winlicense/Themida
auto dest_addr, api_addr, temp;
auto iat_begin, iat_end;
auto vm_begin, vm_end;
auto fp, ret_event;
auto is_exception;
vm_begin = 0x0; // write starting address of your executable's vm section in here
vm_end = 0x0; // write ending address of your executable's vm section in here
iat_begin = 0x0; // write starting address of your executable's IAT in here
iat_end = 0x0; // write ending address of your executable's IAT in here
fp = fopen("D:\\Your-exe-IAT-fix.log", "w"); // replace your log file name in here
for(dest_addr = iat_begin; dest_addr < iat_end; dest_addr = dest_addr + 4)
{
temp = get_dword(dest_addr);
if(temp >= vm_begin && temp < vm_end)
{
msg("%x : %x : ", dest_addr, temp);
fprintf(fp, "%x : %x : ", dest_addr, temp);
jumpto(temp);
refresh_idaview_anyway();
eip = temp;
api_addr = temp;
while((eip >= vm_begin && eip < vm_end))
{
step_until_ret();
wait_for_next_event(WFNE_SUSP, -1);
if(ret_event == EXCEPTION)
{
is_exception = 1;
break;
}
}
if(is_exception == 1)
break;
api_addr = eip;
patch_dword(dest_addr, api_addr);
msg("fixed : %x : %s\n", api_addr, get_name(api_addr));
fprintf(fp, "fixed : %x : %s\n", api_addr, get_name(api_addr));
}
}
fclose(fp);
msg("Done.\n");
Usage : 1. Execute target process fully. 2. Suspend target process and dump process image. 3. Open dumped image and decide both IAT address range and vm code section range in IDA. 4. Attach IDA local debugger to suspended target process. 5. Suspend all threads of target process except for current thread(for avoiding anti-debugger protection). 6. Load above script in IDA and change beginning/ending addresses of IAT and vm code section and your log file name. 7. Execute IDA script, wait for completion of script running and check log files for correctness. 8. Compete dumping and making new IAT by using Scylla. Last edited by Carina0206; 07-22-2026 at 15:05. |
| The Following User Says Thank You to Carina0206 For This Useful Post: | ||
kernel (07-22-2026) | ||
|
#2
|
|||
|
|||
|
Hi, thank you for the script. First time i see IDA script for fixing IAT. The script looks very simple. Are you sure it works without landing at OEP and fixing OEP or you have to enter OEP manually after fixing IAT? Themida also obfuscates the resources. They also have to be fixed.
|
|
#3
|
|||
|
|||
|
Quote:
You need to input only correct original IAT starting address and its size. But if you want to restore dumped image into fully runnable executable, you have to find OEP and fix it in dumped image, and then when eip reached to OEP(by using method to write 2 bytes 0xEB, 0xFE in OEP for infinite looping in OEP) you have to dump image and fix IAT. And as talking about resource, in most often cases, all resources are recovered after complete all operations in Scylla because all obfuscated resources are fully recovered on memory in run-time. Last edited by Carina0206; 07-22-2026 at 18:14. |
![]() |
| Thread Tools | |
| Display Modes | |
|
|