WIN32程序挂钩SetLastError,输出错误描述到控制台

WIN32程序挂钩SetLastError,输出错误描述到控制台

作者:徐灵甫

一、窗口模式应用程序(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;
}

(全文完)

http://blog.csdn.net/jiangxinyu/article/details/5386000

时间: 2024-10-19 10:59:48

WIN32程序挂钩SetLastError,输出错误描述到控制台的相关文章

一起学libcef--搭建自己的libcef运行环境(Win32程序,错误C2220解决方案)

转自 http://blog.csdn.net/wangshubo1989/article/details/50180413 现在就来讲讲如何在自己的win32程序中搭建libcef运行环境. 首先就是建一个空的win32项目,例如名字为TestLibCef. 1. cefsimple目录(注意是拷贝文件夹)拷贝到新工程下并包含在项目中(注意,是TestLibCef\TestLibCef文件夹下) 2. 并在TestLibCef\TestLibCef文件夹下,新建一个dll文件夹 源码把Debu

Oracle错误——ORA12514:监听程序当前无法识别连接描述符中请求的服务

在连接数据库的时候,有时会遇到一个"ORA12514:监听程序当前无法识别连接描述符中请求的服务"的错误,这个错误其实就是数据库动态注册(关于动态注册会在稍后讲解)不生效,导致监听器无法识别客户端连接符中提供的服务名,从而拒绝建立数据库连接时报的错误信息,所以就需要对监听器配置做修改. 在这里,还需对问题进行细化,有时候可能会发现,在刚开启监听器的时候会发生这个错误,但过了一会再进行连接就不会报错,这其实是因为动态注册需要时间,而刚开启监听器时,数据库还未注册到监听器,导致报错,这种情

使用AllocConsole在Win32程序中调用控制台调试输出

近期一个Win32窗口项目中,调试时经常需要输出调试信息以追踪数据流及程序运行状态. 起初我封装了一系列文件操作,实现了日志形式的调试信息输出,但在后期的使用过程中越发觉得颇不顺手.那么,如何方便地在Win32程序中使用控制台进行调试输出?答案如题:AllocConsole函数和C-Runtime的freopen函数.具体操作流程如下: 打开控制台 重定向输出流至控制台 执行调试信息输出操作 完整代码如下: SetConsoleTitle(_T("Debug Output")); fr

引用 运行asp.net程序时候,编译器错误消息: CS0016: 未能写入输出文件“c:\WINDOWS\Microsoft.NET\Fra

引用 运行asp.net程序时候,编译器错误消息: CS0016: 未能写入输出文件“c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\asaa\6afc8e18\e1c3edea\App_Web_masterpage.master.fdf7a39c.r2drwb6q.dll”--“拒绝访问. ” 运行asp.net程序时候,编译器错误消息: CS0016: 未能写入输出文件“c:\WINDOWS\Micr

关于Oracle报“ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务”错误

关于Oracle报“ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务”错误原因:listener.ora中没有指定监听服务器名. 如下是解决思路: 尝试1.通过重启服务的方式启动数据库,再次连接仍无法连接服务器. 尝试2.既然第一种方法不能解决问题,那就第二种方法.考虑监听listener.ora 步骤如下: 在oracle服务器Oracle安装目录(我的在C:\oracle\product\10.2.0\db_1\NETWORK\ADMIN下,每个人的不一样,根据自己的情况

第二章--Win32程序运行原理 (部分概念及代码讲解)

学习<Windows程序设计>记录 概念贴士: 1. 每个进程都有赋予它自己的私有地址空间.当进程内的线程运行时,该线程仅仅能够访问属于它的进程的内存,而属于其他进程的内存被屏蔽了起来,不能被该线程访问. PS:进程A在其地址空间的0x12345678地址处能够有一个数据结构,而进程B能够在其地址空间的0x12345678处存储一个完全不同的数据.彼此不能访问. 2. 在大多数系统中,Windows将地址空间的一半(4GB的前一半,0x00000000-0x7FFFFFFF)留给进程作为私有存

ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务解决

问题:Oracle主服务和监听器服务已经启动,使用SQL Plus能够正常连接,使用PL SQL Developer连接报次错误:ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务.如图: 解决: 打开H:\Oracle\product\11.2.0\dbhome_1\NETWORK\ADMIN(不同机器目录可能不同)目录下的listener.ora文件,发现此文件内容如下: #listener.ora Network Configuration File: H:\Ora

ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务 的解决方法

今天用PL/SQL连接虚拟机中的Oracle数据库,发现报了“ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务”错误,也许你也遇到过,原因如下: oracle安装成功后,一直未停止数据库(即数据库是启动的),客户端配置成功后,应该一直不会有什么问题. 有时把Oracle安装在虚拟机中,而且Oracle安装完毕后,没在进行任何监听的配置,则虚拟机再启动,则就会出现ORA-12514的问题. 如下是解决思路: 根据出错信息判断出客户端未监听到实例服务名 1.通过重启服务的方式启动

windows php 5.5 执行exe 不是有效的win32程序

双击运行php-cgi.exe弹出对话框提示不是有效的win32应用程序.此为版本问题,PHP5.5版本 最低要运行于操作系统版本号最低要6.0 ,而WINDOWS 2003 系统为5.2 因此无法运行,故而提示此错误.WIN2003 下最高只能安装PHP5.4X的版本了. windows php 5.5 执行exe 不是有效的win32程序,布布扣,bubuko.com