1

次の ASM コードがあります。

USE32
Start:
jmp Main
    struc st
        .stLong resd 1
        .stWord resw 1
        .stBuffer   resb    32
    endstruc

    mystruc:
    istruc st
        at st.stLong, dd 1
        at st.stWord, dw 1
    iend
Main:
    mov eax, 1
    mov [mystruc+st.stLong], eax

NASM を使用してコンパイルし、次のコードを使用して、Visual C++ のデバッグ モードで生成されたバイナリを (段階的に) 実行しようとしました。

unsigned char hexData[50] = {
    0xEB, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xA3,
    0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00 
};




__asm{
    lea eax, hexData
    call eax
}

問題は、最初の命令 (jmp Main) を実行すると、常にアクセス違反例外が発生することです。:( ここで実際に何が起こっているのかわかりません。何が問題なのか教えてください。

4

2 に答える 2

1

メモリにはさまざまな保護機能があり、読み取り、書き込み、または実行可能です。デフォルトでは、コードインジェクションを回避したり、コードへの攻撃を悪用したりするために、ユーザーが定義したデータメンバーは実行可能ではありません。ここには2つのオプションがあります。

// Remember this function at least allocate a page that is usually 4096 byte
// Use GetSystemInfo to get page size.
void* pvExecutableMem = VirtualAlloc(NULL, 50, MEM_RESERVE | MEM_COMMIT,
    PAGE_EXECUTE_READWRITE);
// Resulting page is executable
memcpy( pvExecutableMem, hexData, 50 );
// Now you can execute this page
__asm {
    mov eax, pvExecutableMem
    call eax
}

別のアプローチは、次の保護タイプを変更することですhexData

DWORD dwOldProt;
VirtualProtect( hexData, sizeof(hexData), PAGE_EXECUTE_READWRITE, &dwOldProt );

ただし、VirtualXXX関数はページで機能し、50バイトのメモリしか処理できないため、これによりメモリの他の部分のメモリ保護が変更され、セキュリティの脆弱性が発生する可能性があります。

于 2012-10-21T18:46:06.427 に答える
0

補足(コメントを追加できません..)

__asm{
    lea eax, hexData
    call eax
}

hexData を呼び出すためにインライン アセンブラは必要ありません。MSVC x32 では問題ないかもしれませんが、MSVC x64 にはインライン アセンブラがないことに注意してください。

次のアプローチを使用して、バイナリ配列のコードを呼び出すことができます。

#include <iostream>
#include <ostream>
using namespace std;

namespace Namespace
{
    namespace Aux
    {
        extern "C" unsigned char hexData[]={0xC3};
    }
    extern "C" void hexData();
}

int main()
{
    Namespace::hexData();
    cout << "alive!" << endl;
    return 0;
}

アクセス違反を修正するには、BigBoss のアドバイスに従ってください。たとえば、次のコードは MSVC x64 で問題なく動作します。

#include <iostream>
#include <windows.h>
using namespace std;

namespace Namespace
{
    namespace Aux
    {
        extern "C" unsigned char hexData[]={0xC3};
    }
    extern "C" void hexData();
}

int main()
{
    DWORD dwOldProt;
    VirtualProtect( Namespace::Aux::hexData, sizeof(Namespace::Aux::hexData), PAGE_EXECUTE_READWRITE, &dwOldProt );
    Namespace::hexData();
    cout << "alive!" << endl;
    return 0;
}
于 2012-10-21T19:09:59.327 に答える