Thunk,thunk,thunk

---------------------------

作 者:intret

时 间:2011年3月13日星期日

源码格式: VS2008 工程,其实无所谓版本

源码下载:Thunk v0.4 by intret

---------------------------

【摘要】

Thunk是一种技术,你觉得它是不是Knuth(Donald.E.Knuth 爷爷的名字)反过来而得的呢?它做了运行时函数行为的更改,即当执行了Thunk代码,Thunk代码会转而执行类成员函数代码,而这段Thunk代码是精心构造的,包括参数入栈和堆栈平衡工作,当然ATL有ATL的Thunk,我也写了一段。

【用处】

在需要把类成员函数当做普通回调函数来使用的时候,比如窗口过程、线程的Proc、计时器的Proc等),请放心,几行汇编代码并不会影响窗口过程的调用速率。

目录

【摘要】    1

【用处】    1

『一』函数调用约定(Call convention)    2

1.普通回调函数__stdcall方式的调用    2

2.类成员函数__stdcall方式调用    2

『二』汇编指令    3

1.CALL指令    3

2.JMP指令    3

『一』函数调用约定(Call convention)

1.普通回调函数__stdcall方式的调用

CALLBACK在默认情况下被宏定义定义为:__stdcall.我们看窗口过程函数的实现和被调用:

LRESULT CALLBACK WindowProc( HWND hwnd,    UINT uMsg, WPARAM wParam, LPARAM lParam )

{

return 5;

}

void main()

{

//…主函数的准备工作

WindowProc(NULL, 1, 2, 3);

01361C8E push 3 // 第4个参数入栈

01361C90 push 2 // 第3个参数入栈

01361C92 push 1 // 第2个参数入栈

01361C94 push 0 // 第1个参数入栈

01361C96 call WindowProc (136128Fh) // 调用窗口过程函数,call导致下一条指令地址01361C96+6入栈

}

// …主函数的收尾工作

2.类成员函数__stdcall方式调用

class Wnd

{

public:

int __stdcall WndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)

{

return 0;

};

};

void main()

{

Wnd wnd;

wnd.WndProc( NULL, 2, 3, 4);

000F13EB push 4

000F13ED push 3

000F13EF push 2

000F13F1 push 0

000F13F3 lea eax,[wnd] // this指针地址

000F13F6 push eax // 至此压入了5个参数,编译器添加了this指针参数

000F13F7 call Wnd::WndProc (0F104Bh)

}

『二』汇编指令

1.CALL指令

call指令会导致『返回地址』(即call的下一条指令的地址)入栈,然后跳转到目标地址执行代码。

2.JMP指令

JMP指令因为有短跳和长跳:可以只修改IP,也可以同时修改CS和IP。

查询Intel80x86 OPCODES.pdf文件,无条件跳转有如下类型,引用如下:

JMP-Unconditional Jump (to sam segment)

short

1110 1011 : 8-bit displacement

direct

1110 1001 : full displacement

register indirect

1111 1111 : 11 100 reg

memory indirect

1111 1111 : mod 100 r/m

JMP – Unconditional Jump (to other segment)

direct intersegment

1110 1010 : unsigned full offset, selector

indirect intersegment

1111 1111 : mod 101 r/m

我们可以获取Wnd::WndProc类成员函数的地址0x0F104B,然后jmp至该地址,jmp之前,堆栈需要满足的条件是:

  1. 相对于参数入栈前,入栈后堆栈里面多了6个数。(当然call指令导致返回地址入栈也算在其中)
  2. 第5个入栈的参数是Wnd对象的地址,即this指针。(然后才到call导致的返回地址入栈)

但是,消息处理函数总是会这样调用窗口过程函数,使得窗口过程可以得到消息处理机会:

此时要jmp到Wnd::WndProc之前,堆栈状态不能满足以上条件。

call指令导致的结果是什么呢?我翻开王爽的《汇编语言》,确认了一下它做两件事:

  1. IP或CS:IP入栈。(导致堆栈状态的变化)
  2. 转移。(导致目标地址的代码得到执行)

也就是说,返回地址(下一条指令的地址)的入栈是call导致的,那么this指针在call指令之前就可以自由入栈,而且函数局部变量的寻址是根据EBP的偏移定位的。this入栈导致的栈顶指针ESP的变化不会影响局部变量的定位。

回调函数为__stdcall,类成员函数为__stdcall的Thunk code如下:

pthunk

FF 34 24

push

dword ptr [esp]

pthunk+3

C7 44 24 04 44 33 22 00

mov

dword ptr [esp+4],223344h

pthunk+11

E9 33 22 11 00

jmp

0x00112233

I can write no longer…去年非常用心地写,现在已没有兴趣写了,那就共享之,CSDN源码下载地址在上面。

Thunk,thunk,thunk相关推荐

  1. 在React中加载数据:redux-thunk,redux-saga,suspense,hooks

    目录 介绍 初始设置 模拟服务器 项目和API调用 Redux-thunk Redux-saga Suspense Hooks 结论 介绍 React是一个用于构建用户界面的JavaScript库.经 ...

  2. 关于 redux-thunk 的作用,认识,理解

    关于 redux-thunk 的作用,认识,理解 看这篇文章之前,如果你已经看到一些 redux-thunk 的教程,是不是觉得一头雾水,redux-thunk 到底有什么作用,用在哪里,代码不仅没有 ...

  3. Mysql,SqlServer,Oracle主键自动增长的设置

    Mysql,SqlServer,Oracle主键自动增长的设置 参考文献 http://blog.csdn.net/andyelvis/article/details/2446865 1.把主键定义为 ...

  4. linux启动,重启,停止 jar,.sh脚本

    linux启动,重启,停止 jar,.sh脚本 #配置jar名称 APP_NAME=receiver.jar#使用说明,用来提示输入参数 usage() { echo "Usage: sh ...

  5. 堆栈,数据,文本,heap,bss,text data,stack

    堆栈,数据,文本,heap,bss,text data,stack text data bss stack heap 段 根据APUE,程序分为下面的段:.text, data (initialize ...

  6. TVM示例展示 README.md,Makefile,CMakeLists.txt

    TVM示例展示 README.md,Makefile,CMakeLists.txt TVM/README.md Open Deep Learning Compiler Stack Documentat ...

  7. TVM,Relay,Pass

    TVM,Relay,Pass Relay介绍 主要结合TVM的文档(https://tvm.apache.org/docs/dev/relay_intro.html),介绍一下NNVM的第二代Rela ...

  8. LED芯片,应用品,蓝宝石衬底,集成电路,UV

    LED芯片,应用品,蓝宝石衬底,集成电路,UV 三安主要从事全色系超高亮度LED芯片的研发,生产与销售,产品性能稳定,品质优异. 产品覆盖 三安能够提供全波长范围的LED,产品可覆盖全部可见光和不可见 ...

  9. CPU,GPU,Memory调度

    CPU,GPU,Memory调度 HDD&Memory&CPU调度机制(I/O硬件性能瓶颈) 图1. HDD&Memory&CPU调度图 CPU主要就是三部分:计算单元 ...

  10. 自动驾驶QNX,Linux,Autosar概述

    自动驾驶QNX,Linux,Autosar概述 QNX是一个分布式.嵌入式.可规模扩展的实时操作系统.遵循POSIX.1 (程序接口)和POSIX.2 (Shell和工具).部分遵循POSIX.1b( ...

最新文章

  1. 贪心:expedition 最优加油方法
  2. 南农Nature Microbiology一作顾少华:我与铁载体的这5年
  3. 【笔记】与Android酱的第一周
  4. 第16天学习Java的笔记(标准类,Scanner)
  5. 100米队伍,从队伍后到前_我们的队伍
  6. Ubuntu13下调试USB AUDIO的一些记录
  7. mysql插入日期_初识MySQL
  8. docker部署redis集群_Docker部署Redis集群----第九节(docker-redis哨兵集群“轮询分流”篇实例一)...
  9. arraylist扩容是创建新数组吗 java_Java集合干货——ArrayList源码分析
  10. 最新快手JS逆向分析
  11. matlab gui怎样将结果保存_Processing将串行数据保存用作matlab数据分析
  12. python优先级排序_用Python实现优先级队列的3种方法
  13. python项目代做_ECS 170代做、代写Python、data代做、代做Python程序代写Web开发|代写Database...
  14. 协同oa办公系统在线演示下载地址
  15. 阿里月饼事件,猿方怎么看?
  16. 利用INFOPATH2007VS2005开发MOSS工作流详解 --收藏
  17. Php 类似coffeescript,有什么东西像CoffeeScript for PHP吗?
  18. 2020最新版python基础入门学习视频教程
  19. MOSFET原理与应用
  20. 5G LAN — 技术实现原理

热门文章

  1. 2018.6.14 华为南研所面试经验
  2. linux学习步骤(从入门到精通)
  3. Linux C alarm的使用
  4. MFC中UpdateData(FALSE)与UpdateData(TRUE)的区别
  5. ORA-03113数据库无法正常启动
  6. ext2与ext3的区别
  7. Jmeter 之 Beanshell 用法
  8. 8080端口被占用处理方法
  9. 给力!低代码开发平台广州流辰信息科技助您增辉创价值!
  10. 3D点云 (Lidar)检测入门篇 - PointPillars PyTorch实现