Exetools

Exetools (https://forum.exetools.com/index.php)
-   Community Tools (https://forum.exetools.com/forumdisplay.php?f=47)
-   -   IDA script to fix IAT virtualized/obfuscated by Winlicense/Themida (https://forum.exetools.com/showthread.php?t=21697)

Carina0206 07-22-2026 14:47

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");

In case of x86 executables :
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.

kernel 07-22-2026 16:30

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.

Carina0206 07-22-2026 18:05

Quote:

Originally Posted by kernel (Post 135675)
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.

It doesn't need to fix OEP when dump image and fix IAT in Scylla.
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.


All times are GMT +8. The time now is 19:08.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2026, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX