吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 22009|回复: 48
上一主题 下一主题
收起左侧

[原创] 逆向基础

  [复制链接]
跳转到指定楼层
楼主
鱼无论次 发表于 2017-4-13 09:26 回帖奖励
本帖最后由 鱼无论次 于 2017-4-13 17:39 编辑

如果有错误请各位指正

参考书籍:
C++反汇编与逆向分析技术揭秘
汇编教学 by charme

老码识途


主要内容(不分先后顺序):
1.寻址Main函数入口点(为什么找3个push 1个call)
2.指令地址是如何计算出来的
3.所谓的程序入口地址Main函数
4.调用约定
5.善变的汇编指令

使用工具:
OD
VS2013 Debug版

直接上代码:
非常经典的一个程序Hello World,麻雀虽小五脏俱全
void Hello()
{
     printf("HelloWorld\n");
}
int _tmain(int argc,_TCHAR* argv[]){
     printf("恭喜你找到了Main函数入口地址\n");
       H
ello();
     return0;
}
1.寻址Main函数入口点
找到Main函数入口点就要知道Main函数的入口特征,我们可以通过VS2013调试。F10走出Main函数

我们发现Main函数其实也是一个函数,并非程序一开始就调用MainIDA可以看的更直观)

main函数定义有三个参数
main(intargc,char *argv[],char *envp[])
1.argc:命令行参数个数,整数
2.argv:命令行信息,保存字符串数组首地址的指针变量,是一个指向数组的指针。
3.envp:环境变量的信息,和argv类型相同
参数argv与envp就是两个指针数组,当数组作为参数时,实际上以指针方式进行数据传递,这两个参数可以转换为char**二级指针类型。
默认情况下argv第0项是保存路径字符串的首地址

1.1:OD打开EXE程序

F7跟进遇到了两个call,先去看看第一个call有没有我们要找的特征(3push  1call

很遗憾并不在第一个call

F7跟进第二个call找找看(找3push 1call的函数)

小知识(所谓程序入口地址Main函数):
      我们还可以发现程序并非从Main函数开始运行的,main函数也是一个参数,也需要被人调用。main函数只是我们语法规定的用户入口,而不是应用程序入口。

F7跟进历尽千辛万苦终于找到了


2:解析汇编代码  
   我们用
VS2013来调试比较方便

补充知识:
补码表示:既其正整数值求反加1。比如,-1就是1求反,它只有最后一位是0,其他位均为1,再加上1,那么所有位均为1,即0xFFFFFFFF。对有符号数,最高bit为1,则说明它是一个负数如果对一个补码形式的负数求正整值,就是求反加1。比如,对-1求其整数值,就是对0xFFFFFFFF求反,即0。再加1,就是1。

指令地址是如何计算出来的:
   
E8是call的机器码,占一个字节,后面4个字节是call的地址,小端在内存中存放的是倒序的所以是FFFFFD8B。其实计算机寻址方式分为两种,一种是call 123432(绝对值),另外一种是相对定位就是用偏移量。偏移量是区分正与负(往前往后跳)。
   
FF FF FD 8B最高位是1,所以是负数。将其取反+1后,结果是275,再用call当前的地址00381455-275=3811E0+5(call字节数)=3811E5H

2.1:一些基础知识
基础汇编知识:
   
eax一般是当作函数的返回值
   
push esp-4
   
pop  esp+4
   
Call指令= push 下一条指令(程序从上往下走,jmp到一个地方执行完代码你要记得你回去的路吧)
                   jmp标号处

    Ret指令= pop IP
栈的理解:     
    可以把栈理解成一个箱子,先放进去的东西最后才能拿出来(遵循先进后出的原则)
图片:
第一个先拿出来的是英语书     

第二本拿出来的是数学书

最先进去的语文书,是最后拿出来的


2.2:函数汇编方式展示出来的样子
   
我们必须要了解的是,调用call函数进去的时候它原来是什么样子,执行完call你要给它还原回去,所以每次进去函数就会看见push xxx,因为函数内部要用到

汇编代码详解:
003813C0  push        ebp                                                             //保存ebpebp就相当于esp的备份003813C1
003813C1  mov         ebp,esp                                                    //esp后面要进行操作,所以要让ebp先帮它保存原来的值。这样esp么改变都不怕影响到后面的操作
003813C3   sub         esp,0C0h                                                 //开辟空间
003813C9  push        ebx                                                          //保存寄存器,因为后面要用到
003813CA  push    esi            
003813CB  push    edi      
/*************主要功能把分配的空间全部填CC****************/
003813CC  lea      edi,[ebp-0C0h]   
003813D2  mov    ecx,30h  
003813D7  mov    eax,0CCCCCCCCh  
003813DC  rep stos    dword ptr es:[edi]  
详解:
    stos是串存储指令,它的功能是将eax中的数据放入edi所指的地址中,同时edi增加4个字节。rep使指令重复指令ecx中填写的次数。方括号表示存储器,这个地址实际上是edi的内容所指向地址。这里的stos其实对应的是stosd,其他还有stosbstosw,对应的处理的是412字节,这里对堆栈中30h*4个字节初始化0CC也就是int3指令,这样发生意外时执行堆栈里面的内容会引发调试中断     
/*************主要功能把分配的空间全部填CC****************/
            
printf("Hello World\n");
003813DE mov     esi,esp  
003813E0 push     385858h  
003813E5 call       dword ptr ds:[389114h]  
003813EB  add          esp,4                                                  //堆栈平衡后面会详解(调用约定)
003813EE  cmp          esi,esp                                              //VS自带的堆栈平衡检查
003813F0  call           __RTC_CheckEsp (0381140h)  
       //检查可以直接无视
003813F5  pop           edi  
                                                   //恢复寄存器 ,遵循先进后出的原则                        
003813F6 pop       esi  
003813F7 pop       ebx  
003813F8  add           esp,0C0h  
                                       //用完了记得还原分配的栈空间
003813FE cmp           ebp,esp                                             //无视
00381400  call           __RTC_CheckEsp (0381140h)
       //VS自带的检查
00381405  mov         esp,ebp  
                                         //ebp还给esp
00381407  pop          ebp                                                   //恢复ebp
00381408  ret                                                                    //ret返回
总结:      
      其实很多汇编代码都是系统帮我们生成的,或则是VS自带的检查代码。不要看到汇编代码多就恐惧,很多代码都是套路。

3.调用约定
常用的调用约定分为四种:
_stdcall(windowsAPI默认调用方式):参数压栈方式右到左,函数内平衡,函数结束ret xxx
_cdecl(c/c++默认调用方式):参数压栈方式右到左,函数外平衡堆栈,call后面跟着add esp,xxx
_fastcall:参数压栈方式右到左,寄存器方式传参,函数内平衡堆栈
_thiscall:参数压栈方式右到左,ecx传递this指针,函数内平衡堆栈

渣渣代码:
/*
简要说明:
    this指针应属于指针类型,在32位环境下占4个字节大小,保存的数据为地址信息,"this"可翻译为"这个",因此经过字面的分析可以认为
this指针保存了所属对象的首地址。
*/
#include "stdafx.h"
class TestClass
{
public:
    TestClass(int Number)
    {
        m_nNumber = Number;
    }
    int m_nNumber;
};
void _fastcall Show_fastcall(int nNumA, int nNumB)
{
    printf("_fastcall调用方式%d %d \n", nNumA, nNumB);
}
void _cdecl  Show_cdecl(int nNumA, int nNumB)
{
    printf("_cdecl调用方式%d %d\n", nNumA, nNumB);
}
void _stdcall Show_stdcall(int nNumA, int nNumB)
{
    printf("_stdcall调用方式%d %d\n", nNumA, nNumB);
}
int _tmain(int argc, _TCHAR* argv[])
{
    Show_stdcall(7, 8);
    Show_cdecl(10, 11);
    Show_fastcall(22, 33);
    TestClass Test(argc);
    return 0;
}


_stdcall:参数压栈方式右到左,函数内平衡,函数结束ret xxx
Show_stdcall(7, 8);
00B137A8  push      8                                                           //压栈方式右到左
00B137AA  push      7  
00B137AC  call        Show_stdcall (0B1106Eh)  
00B11580   ret        8                                                           //函数内结束的时候ret 8  平衡堆栈


_cdecl(c/c++默认调用方式):参数压栈方式右到左,函数外平衡堆栈,call后面跟着add esp,xxx
Show_cdecl(10, 11);
00B137B1  push        0Bh
00B137B3  push        0Ah  
00B137B5  call          Show_cdecl (0B111D1h)  

00B137BA  add         esp,8                                                  //函数外平衡堆栈


_fastcall:参数压栈方式右到左,寄存器方式传参,函数内平衡堆栈
好处是:传递效率高,因为是使用寄存器所以函数结束不用清空栈
坏处是:就只能用两个寄存器ecx,edx大于2就只能乖乖的用栈传递参数
Show_fastcall(22, 33);
00BF1553  mov         edx,21h  
00BF1558  mov         ecx,16h  
00BF155D  call        Show_fastcall (0BF1154h)  
         return 0;
00BF1562  xor         eax,eax

例如这个例子:
_fastcall而寄存器比较少,它只使用了ecx,edx保存第一个和第二个参数,其余的放在堆栈操作
Show_fastcall(22, 33,44);

012D1553  push        2Ch                        //大于2个参数只能用栈
012D1555  mov         edx,21h  
012D155A  mov         ecx,16h  
012D155F  call          Show_fastcall (012D11EAh)

call函数内部:
012D1499  mov        esp,ebp  
012D149B  pop         ebp  
012D149C  ret           4                          //函数内平衡堆栈

_thiscall:参数压栈方式右到左,ecx传递this指针,函数内平衡堆栈



4.善变的汇编语言(如果没兴趣可以直接无视)
    我记得有一天上课薛老师给我们发了一套某公司的面试题目是:栈的分配内存方式除了sub esp,xxx还有哪些?其实无非就是考你思维灵不灵活。并非只有1+1=2,条条大路通罗马。
    分配栈内存主要是对esp做减法。
     push xxx
     pushad     
     add esp,负数
   
     dec esp


例如call的调用
正常的call调用:
        push 0      
        push 0
      
        push offset szText
        
        push 0
        
        call MessageBox
非正常call调用:
        push 0        
        push 0
        
        push offset szText
        
        push 0
        
        push offset aa                        //返回地址
        
        push offset MessageBox          //调用函数
      
        lea esp,[esp+4]                      //+4等于返回地址
      
        jmp dword ptr [esp - 4]           //jmp DWORD ptr [esp-4]并不改变ESP的值等于调用函数MessageBox,但是esp值并没有改变还是指向返回地址

aa:
        
        xor eax,eax                             //垃圾代码,只是为了测试
致谢
感谢15PB老师们的辛勤栽培
!

点评

看不懂该文章的小伙伴也不用激动,破解最重要的一点是经验积累,通过自身实践和翻阅大量的破解教程。最后一两年时间从量变到质变提升,什么都不用教水到渠成  发表于 2017-4-14 16:05
我看过《 windows设计原理》和《逆向工程核心原理》以及《精通XX反汇编》第三版,几乎对破解没任何的提升。  发表于 2017-4-14 16:02
这篇文章是c语言程序员理解下的“破解”,就单纯的讲了一下函数组成,从内存空间申请到其反馈寄存器后结束。就算把系统框架彻底学透彻,通过修改框架本身来获得的并不是破解  发表于 2017-4-14 15:59

免费评分

参与人数 36威望 +1 吾爱币 +41 热心值 +35 收起 理由
18974980289 + 1 + 1 用心讨论,共获提升!
blovelies + 1 + 1 热心回复!
iamcjsyr + 1 + 1 谢谢@Thanks!
liu101816 + 1 + 1 我很赞同!
Binarian + 1 + 1 我很赞同!
jaffa + 1 谢谢@Thanks!
noalieri + 1 + 1 谢谢@Thanks!
gxxxlxy + 1 + 1 谢谢@Thanks!
Jambby + 1 + 1 讲的很好,已经收听,希望后续能保持更新
妩美 + 1 + 1 热心回复!
likang + 1 + 1 非常赞的基础教学并非那些演示教学。
Lbf + 1 谢谢@Thanks!
却道天凉好个秋 + 1 + 1 谢谢@Thanks!
LC学破解 + 1 + 1 已答复!
jackjack999 + 1 + 1 用心讨论,共获提升!
聊胜于无丶 + 1 + 1 谢谢@Thanks!
小醜 + 1 + 1 用心讨论,共获提升!
破碎ぃ + 1 + 1 用心讨论,共获提升!
lingdu57 + 1 + 1 谢谢@Thanks!
Maybe-sun + 1 + 1 谢谢@Thanks!
skeep + 1 + 1 用心讨论,共获提升!
kantal + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
hundred + 1 + 1 热心回复!
xuexi= + 1 用心讨论,共获提升!
viply + 1 + 1 谢谢@Thanks!
soyiC + 1 热心回复!
myouter + 1 + 1 我很赞同!
白牙照我去战斗 + 1 + 1 已经处理,感谢您对吾爱破解论坛的支持!
Hmily + 1 + 10 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
靓丽轩 + 1 + 1 谢谢@Thanks!
peter_king + 1 谢谢@Thanks!
慕青 + 1 + 1 用心讨论,共获提升!
w3213848 + 1 + 1 用心讨论,共获提升!
jusdy_xiao7 + 1 + 1 我很赞同!
aixnhc + 1 + 1 我很赞同!
wangsheng66 + 1 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
czwuyang 发表于 2017-4-13 11:15
感谢分享经验。论坛因你而精彩!
3#
fantome 发表于 2017-4-13 11:39
4#
喵呜、 发表于 2017-4-13 13:12
5#
jusdy_xiao7 发表于 2017-4-13 13:25
小白进来学习了 谢谢分享基础教程  谢谢!
6#
SN1t2lO 发表于 2017-4-13 13:41
可以当入门笔记记下来
7#
ganxie 发表于 2017-4-13 13:47
厉害厉害,
8#
z94213715 发表于 2017-4-13 15:06
已复制为doc,慢慢学习,谢谢分享经验!
9#
爆破 发表于 2017-4-13 15:49
大量的文字
10#
lthink 发表于 2017-4-13 15:49
感谢分享,留名备用
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-17 01:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表