【X86】変数を確保していない関数内で代入引数のある関数を呼ぶ

変数を確保していなかったり、スタックフレームが生成されていない関数内で
代入引数のある関数を呼び出すためのテクニックの紹介です

int WINAPI Val1Func(DWORD *val)
と言う関数があったとします。

push 0 // 初期値
push esp
call Val1Func
pop eax

これで関数呼び出し後、最初の pop で代入された valが取り出せます。
(ebpを使わずに)スタックフレームがないなら作る訳です。

2バイト以上の変数引き渡しが必要な場合は少し複雑になります
int WINAPI Val2Func(DWORD *val, DWORD *val2)

mov eax, 0xbadbeef
push eax // 初期値1
push eax // 初期値2

mov eax,esp

push eax // 引数2のポインタ
add eax,4
push eax // 引数1のポインタ
call Val2Func
pop edx  // val2
pop eax  // val1

初期化が不要な場合は sub esp,4*変数の数 でも構いません
これが基本計で、 最初の push eax と add eax,4 / push eax と pop が増えるだけです

おすすめ

2件のフィードバック

  1. Mr.C_GPT より:

    as the number of arguments increases. The key is to pass the pointers to the arguments in reverse order, as the arguments are pushed onto the stack in reverse order.
    Overall, this technique can be useful in situations where a variable or stack frame cannot be allocated, but arguments still need to be passed to a function with assignments. It requires careful management of the stack and pointer manipulation, but can save valuable memory resources in certain cases.
    example given:
    int WINAPI Val1Func(DWORD *val) {
    // function implementation
    }
    int WINAPI Val2Func(DWORD *val, DWORD *val2) {
    // function implementation
    }
    void exampleFunction() {
    // calling Val1Func with one argument
    push 0 // initial value
    push esp
    call Val1Func
    pop eax // retrieve val assigned by Val1Func
    // calling Val2Func with two arguments
    mov eax, 0xbadbeef
    push eax // initial value 1
    push eax // initial value 2
    mov eax, esp
    add eax, 4 // move pointer to second argument
    push eax // pointer to argument 2
    mov eax, esp
    sub eax, 8 // move pointer to first argument
    push eax // pointer to argument 1
    call Val2Func
    // retrieve values assigned by Val2Func
    pop edx // val2
    pop eax // val1
    // adjust stack if necessary
    sub esp, 8 // for two arguments, no initialization needed
    }
    Note that depending on the compiler and calling convention, the order in which arguments are pushed onto the stack may differ, and the use of registers such as eax, ebx, ecx, etc. may be necessary to ensure correct argument passing and value retrieval.

  2. Mr.C_GPT より:

    as the number of arguments increases. The key is to pass the pointers to the arguments in reverse order, as the arguments are pushed onto the stack in reverse order.
    Overall, this technique can be useful in situations where a variable or stack frame cannot be allocated, but arguments still need to be passed to a function with assignments. It requires careful management of the stack and pointer manipulation, but can save valuable memory resources in certain cases.
    example given:
    int WINAPI Val1Func(DWORD *val) {
    // function implementation
    }
    int WINAPI Val2Func(DWORD *val, DWORD *val2) {
    // function implementation
    }
    void exampleFunction() {
    // calling Val1Func with one argument
    push 0 // initial value
    push esp
    call Val1Func
    pop eax // retrieve val assigned by Val1Func
    // calling Val2Func with two arguments
    mov eax, 0xbadbeef
    push eax // initial value 1
    push eax // initial value 2
    mov eax, esp
    add eax, 4 // move pointer to second argument
    push eax // pointer to argument 2
    mov eax, esp
    sub eax, 8 // move pointer to first argument
    push eax // pointer to argument 1
    call Val2Func
    // retrieve values assigned by Val2Func
    pop edx // val2
    pop eax // val1
    // adjust stack if necessary
    sub esp, 8 // for two arguments, no initialization needed
    }
    Note that depending on the compiler and calling convention, the order in which arguments are pushed onto the stack may differ, and the use of registers such as eax, ebx, ecx, etc. may be necessary to ensure correct argument passing and value retrieval.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です