issues with threads when using frida-tools to attach code

I have the following frida javascript code, which find code caves for data and code then make sure that the code segment is rwx and at address 4012A5 patches a messagebox with a jump to a codecave code place and then jump back to the original code. The application has four threads, the script run fine up to the point that give access violation, I will include all the relevant code and output.

'use strict';

const currentModule = Process.getModuleByName(Process.mainModule.name);
const targetAddress = ptr('0x4012A5');
console.log('Module base:', currentModule.base);
console.log('Target address:', targetAddress);



function findCodeCaveDATA(size) {
    const scanPattern = '00'.repeat(size);
    
    for (const { base, size, protection } of currentModule.enumerateRanges('rw-')) 
    {
        console.log(`Scanning range for data: base: ${base}, size: 0x${size.toString(16)}, protection: ${protection}`);
        //if (protection.indexOf('w') !== -1 || protection.indexOf('x') !== -1) 
        //{
            const results = Memory.scanSync(base, size, scanPattern);
            if (results.length > 0) 
            {
                console.log(`Found code cave for putting data at address ${results[0].address}`);
                console.log(``);
                return results[0].address;
            }
        //}
    }
    
    console.log('Module size: 0x' + currentModule.size.toString(16));
    console.log('Code cave size needed: 0x' + size.toString(16));
    
    return null;
}

function findCodeCaveCODE(size) {
    const scanPattern = '00'.repeat(size);
    
    for (const { base, size, protection } of currentModule.enumerateRanges('r-x')) 
    {
        console.log(`Scanning range for code: base: ${base}, size: 0x${size.toString(16)}, protection: ${protection}`);
        //if (protection.indexOf('w') !== -1 || protection.indexOf('x') !== -1) 
        //{
            const results = Memory.scanSync(base, size, scanPattern);
            if (results.length > 0) 
            {
                console.log(`Found code cave for putting code at address ${results[0].address}`);
                console.log(``);
                return results[0].address;
            }
        //}
    }
    
    console.log('Module size: 0x' + currentModule.size.toString(16));
    console.log('Code cave size needed: 0x' + size.toString(16));
    
    return null;
}

// For code Segment
function ensureExecutePermissions(address, size) 
{
    Memory.protect(address, size, 'rwx');
}

function calculateRelativeJump(from, to) 
{
    const diff = to.sub(from).sub(5);                                // -5 for the size of the jmp instruction itself
    return new Uint8Array(new Int32Array([diff.toInt32()]).buffer);
}

const caption = "Frida Message";
const text = "Hello from Frida!";
const trampolineSize = 5; // Size of a JMP instruction
const originalInstructions = Memory.readByteArray(targetAddress, trampolineSize);

// Calculate required size for code cave
const messageBoxCode = [
    0x60,                                // pushad
    0x6A, 0x00,                          // push 0
    0x68, 0x00, 0x00, 0x00, 0x00,        // push text (address to be filled)
    0x68, 0x00, 0x00, 0x00, 0x00,        // push caption (address to be filled)
    0x6A, 0x00,                          // push 0
    0xFF, 0x15, 0x00, 0x00, 0x00, 0x00,  // call MessageBoxA (address to be filled)
    0x61,                                // popad
];

// Required size for DATA
const requiredSizeDATA = caption.length + 1 + text.length + 1; // 

// Required size for CODE
const requiredSizeCODE = messageBoxCode.length + trampolineSize + 5; // +5 for final jump back


// Find a code cave for Data
const codeCaveData = findCodeCaveDATA(requiredSizeDATA);

// Find a code cave for Code
const codeCaveCode = findCodeCaveCODE(requiredSizeCODE);

if (codeCaveData && codeCaveCode) {
    console.log('Code cave for putting Data found at:', codeCaveData);
    console.log('Code cave for putting Code found at:', codeCaveCode);    

    // Ensure execute permissions for code segment
    ensureExecutePermissions(codeCaveCode, requiredSizeCODE);

    // Write strings to code cave DATA
    const captionAddress = codeCaveData;
    const textAddress = codeCaveData.add(caption.length + 1);
    Memory.writeUtf8String(captionAddress, caption);
    Memory.writeUtf8String(textAddress, text);

    
    // Prepare MessageBox code
    const codeAddress = codeCaveCode.add(0); // 0 because in separate code segment
    const messageBoxA = Module.getExportByName('user32.dll', 'MessageBoxA');
    
    // Write address for push text
    messageBoxCode[4] = textAddress.toInt32() & 0xFF;
    messageBoxCode[5] = (textAddress.toInt32() >> 8) & 0xFF;
    messageBoxCode[6] = (textAddress.toInt32() >> 16) & 0xFF;
    messageBoxCode[7] = (textAddress.toInt32() >> 24) & 0xFF;
    
    // Write address for push caption
    messageBoxCode[9] = captionAddress.toInt32() & 0xFF;
    messageBoxCode[10] = (captionAddress.toInt32() >> 8) & 0xFF;
    messageBoxCode[11] = (captionAddress.toInt32() >> 16) & 0xFF;
    messageBoxCode[12] = (captionAddress.toInt32() >> 24) & 0xFF;
    
    // Write address for messageBoxA function
    messageBoxCode[17] = messageBoxA.toInt32() & 0xFF;
    messageBoxCode[18] = (messageBoxA.toInt32() >> 8) & 0xFF;
    messageBoxCode[19] = (messageBoxA.toInt32() >> 16) & 0xFF;
    messageBoxCode[20] = (messageBoxA.toInt32() >> 24) & 0xFF;

 
    // Write MessageBox code to code cave
    Memory.writeByteArray(codeAddress, messageBoxCode);

   
    // Write jump back to original code
    const jumpBackAddress = targetAddress.add(trampolineSize);
    const jumpBackCode = [0xE9, ...calculateRelativeJump(codeAddress.add(messageBoxCode.length), jumpBackAddress)];
    Memory.writeByteArray(codeAddress.add(messageBoxCode.length), jumpBackCode);


    // Write jump to code cave at original address
    const jumpToCodeCave = [0xE9, ...calculateRelativeJump(targetAddress, codeAddress)];
    Memory.patchCode(targetAddress, trampolineSize, (code) => {
        Memory.writeByteArray(code, jumpToCodeCave);
    });

    console.log('Code injected successfully');

    // Verify permissions after writing all the code
    console.log('Verifying permissions...');
    const caveProt = Process.findRangeByAddress(codeCaveCode);
    console.log('Code cave Code protection:', caveProt.protection);
    if (caveProt.protection.indexOf('x') === -1) {
        console.log('Warning: Code cave is not executable. Attempting to set execute permission...');
        Memory.protect(codeCaveCode, requiredSize, 'rwx');
    }
} else {
    console.log('Failed to find a suitable code cave');
}

// Add exception handler to catch any errors
Process.setExceptionHandler(function(ex) {
    console.log('Exception:', JSON.stringify(ex, null, 2));
    return false;
});

// Wait for the patched code to be reached
Interceptor.attach(targetAddress, 
{
    onEnter: function(args) 
    {
        console.log('Patched code reached');
        try 
        {
            const codeAddress = codeCaveData.add(caption.length + 1 + text.length + 1);
            Interceptor.attach(codeAddress, 
            {
                onEnter: function(args) 
                {
                    console.log('Injected code executed');
                }
            });
        } catch (error) 
        {
            console.log('Error attaching to injected code:', error);
        }
    }
});

The output of this script is:

Spawning `target.exe`...
Module base: 0x400000
Target address: 0x4012a5
Scanning range for data: base: 0x4a5000, size: 0x17000, protection: rw-
Found code cave for putting data at address 0x4a53d8

Scanning range for code: base: 0x401000, size: 0xa4000, protection: r-x
Found code cave for putting code at address 0x497371

Code cave for putting Data found at: 0x4a53d8
Code cave for putting Code found at: 0x497371
Code injected successfully
Verifying permissions...
Code cave Code protection: rwx
Spawned `target.exe`. Resuming main thread!
Exception: {
  "message": "access violation accessing 0x923cc360",
  "type": "access-violation",
  "address": "0x401117",
  "memory": {
    "operation": "read",
    "address": "0x923cc360"
  },
  "context": {
    "pc": "0x401117",
    "sp": "0x19ff48",
    "eax": "0x64697246",
    "ecx": "0x19ff64",
    "edx": "0x96fa48",
    "ebx": "0x19ff60",
    "esp": "0x19ff48",
    "ebp": "0x19ff50",
    "esi": "0x401000",
    "edi": "0x401000",
    "eip": "0x401117"
  },
  "nativeContext": "0x19fae8"
}
[Local::target.exe ]-> Process terminated
[Local::target.exe ]->

Thank you for using Frida!

The code that causes the exception is:

.text:0040110C ___System__GetTls proc near             ; CODE XREF: sub_48BA5C↓p
.text:0040110C                                         ; sub_48BA5C+E↓p ...
.text:0040110C                 mov     eax, dword_4A53D8
.text:00401111                 mov     edx, fs:2Ch
.text:00401117                 mov     eax, [edx+eax*4]
.text:0040111A                 retn
.text:0040111A ___System__GetTls endp

The application is a borland c++ builder 6 and there are four threads

I do not understand what is happening, all the code and locations checked carefully, and also patching the application manually clearly works with no issues.

I’m hoping that someone experts with threads can help me to troubleshoot this issue.

To sum up this part of the frida js script is not executed in full:

// Wait for the patched code to be reached
Interceptor.attach(targetAddress, 
{
    onEnter: function(args) 
    {
        console.log('Patched code reached');
        try 
        {
            const codeAddress = codeCaveData.add(caption.length + 1 + text.length + 1);
            Interceptor.attach(codeAddress, 
            {
                onEnter: function(args) 
                {
                    console.log('Injected code executed');
                }
            });
        } catch (error) 
        {
            console.log('Error attaching to injected code:', error);
        }
    }
});

New contributor

mario russo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật