寻找IT黑马,觉得自己实力过硬的就进来看看这段代码

Ericz 2013-01-22 03:01:44
大家看看能不能看懂下面的代码
先申明:没有内存错误,没有bug


int _call_num;

void func(int a)
{
int i = 0;
unsigned long adr = 0;
unsigned char *ptr = (unsigned char *)&a;

if(!_call_num) {
for(i = 0; i < a ; ++i) {
ptr -= 4;
adr = *((unsigned long *)ptr);
printf("[func]:%d:%x\n", i, adr);
ptr -= 4;
ptr = (unsigned char *)(*((unsigned long *)ptr));
ptr += 8;
}
_call_num++;
}
}

...全文
4743 44 打赏 收藏 转发到动态 举报
写回复
用AI写文章
44 条回复
切换为时间正序
请发表友善的回复…
发表回复
Ericz 2013-01-28
  • 打赏
  • 举报
回复
引用 37 楼 fdisksys 的回复:
32位通常情况下: func的栈 高地址 a eip ebp C/C++ code?12345678910111213unsigned char *ptr = (unsigned char *)&a; //ptr 指向 a if(!_call_num) { for(i = 0; i < a ;……
非常赞成这样改。
xxb249 2013-01-28
  • 打赏
  • 举报
回复
断点调试 是每一个程序员必须掌握的技能!!
cmail2005 2013-01-28
  • 打赏
  • 举报
回复
37楼说的清楚,程序在32位windows下,vs2008生成debug版可以执行,release版出错。
引用 10 楼 mLee79 的回复:
... 他的程序依赖栈帧, M$VC下得加编译选项 /Oy- gcc 下加上编译选项 -fomit-frame-pointer 他也照样挂. 这种东西还是用汇编写方……
“http://zhidao.baidu.com/question/292315594.html” 哪些情况下 Release 版会出错: 1... 2.优化这是造成错误的主要原因,因为关闭优化时源程序基本上是直接翻译的,而打开优化后编译器会作出一系列假设。这类错误主要有以下几种: 1. 帧指针(Frame Pointer)省略(简称FPO):在函数调用过程中,所有调用信息(返回地址、参数)以及自动变量都是放在栈中的。若函数的声明与实现不同(参数、返回值、调用方式),就会产生错误,但 Debug 方式下,栈的访问通过 EBP 寄存器保存的地址实现,如果没有发生数组越界之类的错误(或是越界“不多”),函数通常能正常执行;Release 方式下,优化会省略 EBP 栈基址指针,这样通过一个全局指针访问栈就会造成返回地址错误是程序崩溃。 可以在 Release 版本中强制加入/Oy-编译选项来关掉帧指针省略。 根据上面几位高手观点完善了一下,不求分数,只想有个清晰的说法。
china_jeffery 2013-01-28
  • 打赏
  • 举报
回复
unsigned char *ptr = (unsigned char *)&a; ptr存储的只是临时变量的地址
边走边瞧 2013-01-28
  • 打赏
  • 举报
回复

#include "stdafx.h"
#include <stdlib.h>

int _call_num = 0;

void func(int a)
{
004113A0  push        ebp  
004113A1  mov         ebp,esp 
004113A3  sub         esp,0E4h 
004113A9  push        ebx  
004113AA  push        esi  
004113AB  push        edi  
004113AC  lea         edi,[ebp-0E4h] 
004113B2  mov         ecx,39h 
004113B7  mov         eax,0CCCCCCCCh 
004113BC  rep stos    dword ptr es:[edi] 
	void *adr = (void *)0;
004113BE  mov         dword ptr [adr],0 
	void    **ptr = (void **)&a;
004113C5  lea         eax,[a] 
004113C8  mov         dword ptr [ptr],eax 
	if(!_call_num)
004113CB  cmp         dword ptr [_call_num (417178h)],0 
004113D2  jne         func+0A7h (411447h) 
	{
		for(int i = 0;i < a;i++)
004113D4  mov         dword ptr [i],0 
004113DB  jmp         func+46h (4113E6h) 
004113DD  mov         eax,dword ptr [i] 
004113E0  add         eax,1 
004113E3  mov         dword ptr [i],eax 
004113E6  mov         eax,dword ptr [i] 
004113E9  cmp         eax,dword ptr [a] 
004113EC  jge         func+9Ah (41143Ah) 
		{
			ptr-- ;
004113EE  mov         eax,dword ptr [ptr] 
004113F1  sub         eax,4 
004113F4  mov         dword ptr [ptr],eax 
			adr = *ptr;
004113F7  mov         eax,dword ptr [ptr] 
004113FA  mov         ecx,dword ptr [eax] 
004113FC  mov         dword ptr [adr],ecx 
			printf("[%d]:%p\n",i,adr);
004113FF  mov         esi,esp 
00411401  mov         eax,dword ptr [adr] 
00411404  push        eax  
00411405  mov         ecx,dword ptr [i] 
00411408  push        ecx  
00411409  push        offset string "[%d]:%p\n" (41563Ch) 
0041140E  call        dword ptr [__imp__printf (4182C4h)] 
00411414  add         esp,0Ch 
00411417  cmp         esi,esp 
00411419  call        @ILT+315(__RTC_CheckEsp) (411140h) 
			ptr--;
0041141E  mov         eax,dword ptr [ptr] 
00411421  sub         eax,4 
00411424  mov         dword ptr [ptr],eax 
			ptr = (void **)(*ptr);
00411427  mov         eax,dword ptr [ptr] 
0041142A  mov         ecx,dword ptr [eax] 
0041142C  mov         dword ptr [ptr],ecx 
			ptr += 2;
0041142F  mov         eax,dword ptr [ptr] 
00411432  add         eax,8 
00411435  mov         dword ptr [ptr],eax 
		}
00411438  jmp         func+3Dh (4113DDh) 
		_call_num++;
0041143A  mov         eax,dword ptr [_call_num (417178h)] 
0041143F  add         eax,1 
00411442  mov         dword ptr [_call_num (417178h)],eax 
	}
}
00411447  pop         edi  
00411448  pop         esi  
00411449  pop         ebx  
0041144A  add         esp,0E4h 
00411450  cmp         ebp,esp 
00411452  call        @ILT+315(__RTC_CheckEsp) (411140h) 
00411457  mov         esp,ebp 
00411459  pop         ebp  
0041145A  ret 
wizard_tiger 2013-01-28
  • 打赏
  • 举报
回复
路过,坐等黑马出现。
wzb56 2013-01-28
  • 打赏
  • 举报
回复
引用 37 楼 fdisksys 的回复:
32位通常情况下: func的栈 高地址 a eip ebp C/C++ code?12345678910111213unsigned char *ptr = (unsigned char *)&a; //ptr 指向 a if(!_call_num) { for(i = 0; i < a ;……
这个好,多明白呀。。 这个与函数的调用规约有关。。
fdisksys 2013-01-27
  • 打赏
  • 举报
回复
32位通常情况下: func的栈 高地址 a eip ebp

unsigned char *ptr = (unsigned char *)&a; //ptr 指向 a
   
          if(!_call_num) {
                  for(i = 0; i < a ; ++i) {
                          ptr -= 4;    //指向eip,函数的返回地址
                          adr = *((unsigned long *)ptr);
                          printf("[func]:%d:%x\n", i, adr);
                          ptr -= 4;   //指向ebp,. 
                          ptr = (unsigned char *)(*((unsigned long *)ptr));//指向调用函数的ebp
                          ptr += 8; //这里+8是为了上面下次定位.
                  }
                  _call_num++;
         }
下面这样写要好一点吧
void func(int a){
    void *adr = (void *)0;
    void    **ptr = (void **)&a;
    if(!_call_num){
        for(int i = 0;i < a;i++){
            ptr-- ;
            adr = *ptr;
            printf("[%d]:%p\n",i,adr);
            ptr--;
            ptr = (void **)(*ptr);
            ptr += 2;
        }
        _call_num++;
    }
}
zy101843 2013-01-27
  • 打赏
  • 举报
回复
就是个打印栈的内容。有什么好稀奇,可能debug版本和release版本的效果还不同,里面的prt -= 4 这种做法非常危险,因为不知道这个程序是64位还是32位。
流泪海豚 2013-01-26
  • 打赏
  • 举报
回复
聆听大牛指导,码农路过!
cmail2005 2013-01-26
  • 打赏
  • 举报
回复
ptr -= 4; ptr -= 4; ptr = (unsigned char *)(*((unsigned long *)ptr));//ptr指向上层函数的调用返回 //后执行的下一指令 ptr += 8;//ptr -= 4;ptr -= 4;后面就不知指到何处了
wanglu343280746 2013-01-26
  • 打赏
  • 举报
回复
完全看不懂,坐等楼下IT黑马出现
半棵树 2013-01-25
  • 打赏
  • 举报
回复
跟 25楼一样!
tan8520 2013-01-25
  • 打赏
  • 举报
回复
这样是不对的 在windows xp sp2之后的系统 release版有很多的保护机制 你不能确定ptr的值一定是上层函数的地址,如果系统加入了“小甜点”呢,那个寄存器的位置就变了。+4是不准确的,而且我觉得你就算知道了调用各层函数的地址有没有用,劫持进程?这个函数可没有溢出漏洞。
swlilike 2013-01-25
  • 打赏
  • 举报
回复
我鄙视写代码不写注释的人!
MFCANDPAI 2013-01-25
  • 打赏
  • 举报
回复
int _call_num; void func(int a) { int i = 0; unsigned long adr = 0; unsigned char *ptr = (unsigned char *)&a;//把a的地址强制转换为无符号字符指针类型,把值赋给相同的指针变量ptr if(!_call_num) { for(i = 0; i < a ; ++i) { ptr -= 4; adr = *((unsigned long *)ptr);//强制转化为无符号长整形类型,然后取值 printf("[func]:%d:%x\n", i, adr);// ptr -= 4; ptr = (unsigned char *)(*((unsigned long *)ptr));//个人觉得这些强制转换可能已经得到无意义的值了 ptr += 8; } _call_num++; } }
redleaves 2013-01-25
  • 打赏
  • 举报
回复
十分依赖栈布局,没有什么实用性.更没有平台通用性. 与其这样,还不如在x86上直接读ebp.arm上读lr,sp....
才仔 2013-01-24
  • 打赏
  • 举报
回复
ptr += 8;是什么意思 ,减8后加8不是死循环了吗?求高手解释
才仔 2013-01-24
  • 打赏
  • 举报
回复
亲爱的赵老师又来刷分了
game_coder 2013-01-24
  • 打赏
  • 举报
回复
依赖栈帧布局 release下一般都有/Oy优化的 这样是不行的
加载更多回复(24)

69,372

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧