寻找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++;
}
}

...全文
4676 44 点赞 打赏 收藏 举报
写回复
44 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
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;后面就不知指到何处了
  • 打赏
  • 举报
回复
完全看不懂,坐等楼下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优化的 这样是不行的
  • 打赏
  • 举报
回复
加载更多回复
相关推荐
发帖
C语言
加入

6.5w+

社区成员

C语言相关问题讨论
申请成为版主
帖子事件
创建了帖子
2013-01-22 03:01
社区公告
暂无公告