打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
一道BT的面试题

   昨天在网上看到一个BT的面试题,代码如下:问题是运行这个程序屏幕上为什么会出现一个  :)  ,就是一个冒号加一个右括号。

      注:环境VC6 SP6 + vista sp2

  1. #include <stdio.h>  
  2.   
  3. int main(int argc, char* argv[])  
  4. {  
  5.  const short int c1 = (short)49920;   
  6.     const int c2 = 1073742008;   
  7.   
  8.     int (*pf)() = (int (*)())&c2;   
  9.   
  10.     printf("%c%c/n", *(char*)pf() - 19, *((char*)pf() + 1) - 49);   
  11.     return 0;   
  12. }  

      我囧,当然是先跑起来看一下,debug下确实在屏幕上打印出来一个 :) ,再看看程序,它把c2的地址强制转换为了一个函数指针,它想干嘛?!然后下面还调用了这个函数,居然没crash,看来是c2里面的数值有点特殊,可能是构造的指令码,懒得分析了,直接把debug下编出来的文件放OD里面看一下,跑到函数调用的地方,如图:

      三个红框的部分是两次调用pf和一次调用printf的位置,前面给c1和c2分配了空间,调用pf实际上直接就是运行EBP-C处的代码也就是指令执行到栈上去了,牛×,第一个call跟进去,如下图:

      那个指令00B8 00004000 C3实际上就是c1和c2的值,可以转换成十六进制看一下,RETN返回之后,EAX中的值是00400000,很神奇的一个数字啊,为什么神奇,因为EXE文件加载到内存中的时候基址就是Ox00400000,所以实际上,这个时候EAX指向的是pe文件的第一个字节。

      PE文件的第一个字节是啥?打开来看下:4D,传说中的MZ。再看第一个图片的代码,函数返回后把EAX加1,然后取指向的值,返回0x5A,接着这个值减去0x31,再存入ECX,计算出来是十进制41,查下ascii表http://apps.hi.baidu.com/share/detail/703688,果然是对应的右括号,第二个冒号也可以同样分析出来,汗。机器码前,了无秘密。

      还有一个问题是,如果我编成release来跑的,直接crash,还是OD看一下是啥问题:

      我囧,怎么这两个变量c1和c2没了……直接去执行堆栈指针指向地址的堆栈上的东东,不crash才怪了。那就给编译器使个障眼法,让它不优化掉这两个变量吧。杯具的代码。

  1. #include "stdafx.h"  
  2. void fun(int* pnData)  
  3. {  
  4.     return;  
  5. }  
  6. int main(int argc, char* argv[])  
  7. {  
  8.     short int c1 = (short)49920;   
  9.     int c2 = 1073742008;  
  10.   
  11.     fun((int*)&c1);  
  12.     fun(&c2);  
  13.   
  14.     int (*pf)() = (int (*)())&c2;  
  15.   
  16.     printf("%c%c/n", *(char*)pf() - 19, *((char*)pf() + 1) - 49);  
  17.   
  18.     return 0;   
  19. }  

 

【END】

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C/C++内存与运行时深入研究
C语言的那些小秘密之变参函数的实现
IOLI crackme分析——从应用中学习使用radare2
C++怎样实现Win32 ASM中的invoke调用 [文字模式]
Segmentation Fault in Linux (2.指针越界和SIGSEGV)
指针
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服