程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> WIN32程序掛鉤SetLastError,輸出錯誤描述到控制台

WIN32程序掛鉤SetLastError,輸出錯誤描述到控制台

編輯:關於VC++

一、窗口模式應用程序(GUI)啟用控制台的方法為:

步驟 方法 1 啟動/關閉控制台 AllocConsole()

FreeConsole()

2 重定向輸入/輸出 freopen("CONIN$","r",stdin)

freopen("CONOUT$","w",stdout)

freopen("CONOUT$","w",stderr)

3 控制台輸入/輸出 #include <conio.h>

#include <stdio.h>

printf(...)

scanf(...)

system("pause")

二、掛鉤API函數的簡單方法為:

1. DEBUG模式下,函數名值為指令“JMP函數體”的地址。指令格式為 “E9 □□□□”,附帶的參數為四字節表示的轉移偏移量。因此“函數 名值 + *(DWORD*)((DWORD)函數名值 + 1)”為函數體入口地址。“使用轉到 反匯編”的功能計算出函數體入口棧指令長度,得出實際入口地址為“函數名 值 + *(DWORD*)((DWORD)函數名值 + 1) + 入口棧指令長度”;

2. RELEASE模式下,函數名值直接為函數體的入口地址。使用“轉到反匯編 ”的功能計算出函數體除退出指令外的指令長度,得出函數出口地址為“函數 名 + 指令長度”,API函數正是這種模式;

3. 使用“::WriteProcessMemory(::GetCurrentProcess(), API函數出口地 址...)”的方法在API函數上掛鉤以下調用:

序號 說明 指令 參數值 1 調用掛鉤函數 E8 □□□□ 掛鉤函數體實際入口地址 2 退出 C2 □□ 函數參數總長度,用於恢復棧的狀態

三、掛鉤API函數SetLastError,並輸出錯誤描述到控制台的范例

#include <stdio.h>
#include <windows.h>
void hook_SetLastError()//為簡化調用掛鉤函數時的棧操作,掛鉤函數無參數和返回值 。
{
if (::GetLastError())
{
 LPVOID lpMsgBuf = 0;
 if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_IGNORE_INSERTS,
    0, ::GetLastError(), LANG_USER_DEFAULT, (LPTSTR) &lpMsgBuf, 0, 0))
 {
  ::printf("ERROR: %d %s", ::GetLastError(), (LPCSTR)lpMsgBuf);
  ::LocalFree(lpMsgBuf);
 }
}
}
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
 unsigned char setup_SetLastError[8] = {0xE8, 0, 0, 0, 0, 0xC2, 4, 0};
#ifdef _DEBUG
 *(unsigned int*)(setup_SetLastError + 1) = (unsigned int)hook_SetLastError +
  *(unsigned int*)((unsigned char*)hook_SetLastError + 1) - (unsigned int) SetLastError - 18;
#else
 *(unsigned int*)(setup_SetLastError + 1) = (unsigned int)hook_SetLastError -
   (unsigned int)SetLastError - 23;
#endif
 ::WriteProcessMemory(::GetCurrentProcess(), (LPVOID)((unsigned int)::SetLastError + 18),
   setup_SetLastError, 8, new SIZE_T);
 ::AllocConsole();
 ::freopen("CONIN$", "r", stdin);
 ::freopen("CONOUT$", "w", stdout);
 //此處添加自己的代碼
 ::WriteProcessMemory(::GetCurrentProcess(), (LPVOID)((unsigned int)::SetLastError + 18),
    setup_SetLastError + 5, 3, new SIZE_T);
 ::system("pause");
 return 0;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved