簡體   English   中英

如何在C程序中修復鈎子(堆棧的還原)

[英]How to fix a Hook in a C program (stack's restoration)

這是一種訓練任務,因為如今(我想)這些方法不再起作用。

使用Win XP和MinGW編譯器。 不涉及特殊的編譯器選項(僅在gcc中聲明一個源文件)。

首先,保存一個地址以退出程序並跳轉到某些Hook函數:

// Our system uses 4 bytes for addresses.
typedef unsigned long int DWORD;

// To save an address of the exit from the program.
DWORD addr_ret;

// An entry point.
int main()
{
   // To make a direct access to next instructions.
   DWORD m[1];

   // Saving an address of the exit from the program.
   addr_ret = (DWORD) m[4];

   // Replacing the exit from the program with a jump to some Hook function.
   m[4] = (DWORD) Hook;

   // Status code of the program's execution.
   return 0;
}       

這段代碼的目標是獲得對系統特權級別的訪問權限,因為當我們返回(應該返回)到系統時,我們只是將程序重定向到某些方法。 該方法的代碼:

// Label's declaration to make a jump.
jmp_buf label;

void Hook()
{
   printf ("Test\n");

   // Trying to restore the stack using direct launch (without stack's preparation) of the function (we'll wee it later).
   longjmp(label, 1);

   // Just to make sure that we won't return here after jump's (from above) finish, because we are not getting stuck in the infinite loop.
   while(1) {}
}

最后,我將陳述一個函數(在我看來)應該修復堆棧指針-ESP寄存器:

void FixStack()
{
   // A label to make a jump to here.
   setjmp(label);

   // A replacement of the exit from this function with an exit from the whole program.
   DWORD m[1];
   m[2] = addr_ret;
}

當然,我們應將這些包含項用於所述程序:

#include <stdio.h>
#include <setjmp.h>

該程序的整個邏輯在我的系統中正常工作,但是我無法還原我的堆棧(ESP),因此該程序返回了錯誤的返回碼。

在上述解決方案之前,我沒有使用跳轉和FixStack函數。 我的意思是這些行是在Hook函數中而不是跳轉和while循環中:

DWORD m[1];
m[2] = addr_ret;

但是,使用此變體,我在退出程序之前在ESP寄存器中得到了錯誤的值(該值比在進入該程序之前該寄存器的值大8個字節)。 因此,我決定以某種方式添加這8個字節(避免在C程序中使用任何ASM代碼)。 這是跳轉到FixStack函數並從中退出的目的(從堆棧中刪除一些值)。 但是,正如我所說,它使用以下命令不會返回程序執行的正確狀態:

echo %ErrorLevel%

所以我的問題非常廣泛:從在使用調試實用程序時提出一些建議(我當時僅使用OllyDbg)開始,到為所描述的Hook實現提供可能的解決方案。

好的,我可以按計划使程序正常運行。 現在我們可以啟動編譯的程序(在Win XP中我使用MinGW),沒有任何錯誤,並且返回正確的代碼。

也許會對某人有所幫助:

#include <stdio.h>
#include <setjmp.h>

typedef unsigned long int DWORD;

DWORD addr_ret;


int FixStack()
{
    DWORD m[1];
    m[2] = addr_ret;

    // This line is very necessary for correct running!
    return 0;
}


void Hook()
{
    printf("Test\n");

    FixStack();
}


int main()
{
    DWORD m[1];

    addr_ret = (DWORD) m[4];

    m[4] = (DWORD) Hook;
}

當然,您似乎已經意識到這僅適用於非常特定的構建環境。 它絕對不能在64位目標上運行(因為地址不是DWORD格式的)。

有什么理由為什么您不想使用C標准庫提供的功能來做到這一點? (或與此非常相似的東西。)

#include <stdlib.h>

void Hook()
{
    printf("Test\n");
}

int main()
{
    atexit(Hook);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM