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

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

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

    转自 http://blog.csdn.net/wangshubo1989/article/details/50180413 现在就来讲讲如何在自己的win32程序中搭建libcef运行环境. 首先就 ...

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

    关于Oracle报“ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务”错误原因:listener.ora中没有指定监听服务器名. 如下是解决思路: 尝试1.通过重启服务的方式启动数 ...

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

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

  4. ORA-12505: TNS: 监听程序当前无法识别连接描述符中所给出的SID等错误解决方法

    程序连接orarle报ORA-12505错误 一.异常{ ORA-12505, TNS:listener does not currently know of SID given in connect ...

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

    学习<Windows程序设计>记录 概念贴士: 1. 每个进程都有赋予它自己的私有地址空间.当进程内的线程运行时,该线程仅仅能够访问属于它的进程的内存,而属于其他进程的内存被屏蔽了起来,不 ...

  6. 控制台程序的中文输出乱码问题(export LC_CTYPE=zh_CN.GBK,或者修改/etc/sysconfig/i18n为zh_CN.GBK。使用setlocale(LC_CTYPE, "");会使用默认办法。编译器会将源码做转换成Unicode格式,或者指定gcc的输入文件的编码参数-finput-charset=GBK。Linux下应该用wprintf(L"%ls/n",wstr))

    今天发现用securecrt登陆时,gcc编译出错时会出现乱码,但直接在主机的窗口界面下用Shell编译却没有乱码.查看了一下当时的错误描述,发现它的引号是中文引号,导致在SecureCRT中显示出错 ...

  7. 什么是消息循环,一个简单的win32程序如何运行?

    预备知识 1.什么是句柄? (HANDLE) 在win32编程中有各种句柄,那么什么是句柄呢? #define DECLARE_HANDLE(name) struct name##_ { int un ...

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

    早上同事用PL/SQL连接虚拟机中的Oracle数据库,发现又报了"ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务"错误,帮其解决后,发现很多人遇到过这样的问 ...

  9. ZeroMQ接口函数之 :zmq_strerror - 获取ZMQ错误描述字符串

    ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq_strerror zmq_strerror(3) ØMQ Manual - ØMQ/4.1.0 Name zmq_ ...

随机推荐

  1. 【wpf基础】wpf MediaElement全屏播放视频功能

    最近在研究如何将视频全屏播放,一开始思路A:弹窗将MediaElement对象add到一个新的全屏窗体,报错 指定的元素已经是另一个元素的逻辑子元素.请先将其断开连接. 后续转换思路B:将本窗体其他控 ...

  2. Eclipse用法和技巧二十四:当git遇上eclipse

    git是非常优秀的代码管理工具,eclipse是非常不错的,免费的IDE.工作中两者碰到一起,有点麻烦了:eclipse对于每个项目会生成一些特定的文件,而这些文件又不是项目必须的,并且每个人的配置是 ...

  3. [PWA] 13. New db and object store

    Create a db: import idb from 'idb'; var dbPromise = idb.open('test-db', 2, function (upgradeDb) { sw ...

  4. tomcat URL简写案例:模拟站点www.baidu.com的訪问

    tomcat URL简写案例:模拟站点  * 实际URL:http://www.baidu.com:8080/myweb/1.html  * 实际位置:F:\mywebapps\myweb\1.htm ...

  5. Oracle 存储过程(2)

    http://www.cnblogs.com/chinafine/archive/2010/07/12/1776102.html http://blog.itpub.net/29485627/view ...

  6. Django初探--开发环境搭建(笔记)

    1. Django框架的安装 (1) 下载Django源码 Django-1.7.11.tar.gz,并解压,网址:https://www.djangoproject.com/download/ (2 ...

  7. My way to Python - Day05 - 面向对象

    思维导图

  8. Spring.Net+NHibernate+asp.net mvc + easyui

    毕业4个月的入手项目..前段时间在公司一直做的维护..为了弄明白自己也就跟着写了一个,目前也正在学习:不对的或者是有更好的还请各位赐教. 在学习的过程中主要参考::http://www.cnblogs ...

  9. css标签选择器

    /*标签选择器*/ input[type="text"] { width: 60%; } </style>

  10. WebSocket协议

    websocket 简介 (2013-04-09 15:39:28) 转载▼   分类: websocket 一 WebSocket是html5新增加的一种通信协议,目前流行的浏览器都支持这个协议,例 ...