作者:Crazyman_Army

原文来自:https://bbs.ichunqiu.com/thread-43469-1-1.html

0x00知识回顾 (由于笔者省事,没开XP虚拟机,而且没关闭ASLR,所以每次重载的内存地址会不一样)

在第一章的内容中,笔者已经讲了OllyDbg(简称OD)的界面介绍以及基础的操作,普及了常用的汇编指令

上次课在底下的附件中,我留下了一个演示样例,大家载入OD后搜索到字符串点击跟踪到反汇编窗口的时候会发现与第一章所讲的程序的框架不太一样.

尤其可见多出了很多的call指令,call指令在汇编中就是调用子程序,下面放出代码,各位同学可以比对一下与上篇文件所贴出代码的不同

代码如下:

#include <windows.h>

#include <tlhelp32.h>

#include <stdio.h>

BOOL getProcess(const char *procressName);

BOOL getProcess(const char *procressName)

{

char pName[MAX_PATH];

strcpy(pName, procressName);

CharLowerBuff(pName, MAX_PATH);

PROCESSENTRY32 currentProcess;

currentProcess.dwSize = sizeof(currentProcess);

HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (hProcess == INVALID_HANDLE_VALUE)

{

printf("CreateToolhelp32Snapshot()调用失败!\n");

return FALSE;

}

_asm NOP;

BOOL bMore = Process32First(hProcess, ¤tProcess);

while (bMore)

{

CharLowerBuff(currentProcess.szExeFile, MAX_PATH);

if (strcmp(currentProcess.szExeFile, pName) == 0)

{

CloseHandle(hProcess);

return TRUE;

}

bMore = Process32Next(hProcess, ¤tProcess);

}

CloseHandle(hProcess);

return FALSE;

}

int main()

{

char* process = "explorer.exe";

if (getProcess(process))

{

printf("发现explorer.exe\n");

system("pause");

exit(0);

}

else

{

printf("没有发现explorer.exe\n");

printf("Cracke Success!");

}

getchar();

return 0;

}

从代码角度来看,很明显,这次笔者讲判断进程封装成一个返回布尔值的函数,所以才会在核心判断部分出现如此多的调用,那这当然不能像上次一样改一步简单的跳转就解决问题,如果改得不对就会造成程序的崩溃。

下面笔者通过三种方法来绕过这个检验explorer.exe进程的小程序

方法一:修改判断进程的变量名称

在只能搜索中,我们看到了explorer.exe这个进程的字符串,我们用鼠标选中后,双击,在反汇编窗口中跟随

反汇编窗口显示的如下:

用鼠标选中这条代码右键 -> 数据窗口中跟随–> 内存地址

数据窗口随之发生了变化,在数据窗口上选中一部分数据右键

右键 –> 复制到可执行文件

点击放大键放大该窗口

然后就可以胡乱修改explorer.exe这个字符串

笔者这里就随便修改了

修改如下:

在窗口上右键,保存文件

文件保存成功

点击运行

第一种方法破解成功

方法二:确认过眼神,你不是我们的人

回到判断的核心代码,这里面是jnz来进行进程的判断

那jnz 的全拼写是 jump not zero 那其的反义词即为 jump

Zero,即为jz 或者 je (jump equal),那这样原来的判断explorer.exe就改为了不判断explorer.exe,这样就绕过了检测进程.

下面我们来实际操作,用鼠标选中后

双击

将jnz short 00291158改为 jz short 00291158或者 je short 00291158,将使用nop填充勾掉

点击汇编

然后再保存文件,保存后运行

第二种破解方法成功

方法三:条件改强制

如下图,这个jnz short 00101158是如果zf=0时就会跳转

而jnz所在代码的地址为00101137,我们尝试让其无条件跳转到00101137下面一个地址,也就是00101139(下图红框锁标注的区域)

双击地址为00101137的那条代码,如下图所示 将jnz short 00101158改为jmp short 00101139,点击汇编

点击运行按钮

程序运行截图:

很显然破解成功了,那具体是怎么个原理呢,我们这里留个悬念,等用od能分析一个简单程序后,我们回过头来解释这个问题

00x01 用OllyDbg分析一个简单的程序

下面,笔者将带领同学去用OllyDbg来分析一个简单的程序

笔者为了方便写了一个简单的判断输入数字的程序,代码如下:

载入OD

反汇编窗口上右键中文搜搜引擎 -> 智能搜索

跟踪后的代码可以看到:

在有程序保护的情况下,你可能无法搜索到字符串,这里先不讨论,笔者将带领同学一步一步分析这个简单的程序

这里面push ebp movebp,esp push ecx可以简单的理解为源码中的int main()后的{   (这里为了方便于理解)

push Text.013E3E34,push的意思自然是压栈

这里就不得不要说说C语言中的printf

下面是printf的函数声明

int printf(const char *format, ...);

那在默认的情况下,printf函数应该有一个const char*型的参数,而这一行就是把“Please Input Flag Number:”这个字符串指针当成参数1,压入栈中

mov [local.1],0x0

那究竟这个[local.1]是何方神圣呢?

我们选中这段代码

右键 -> 分析 –> 从模块中删除分析

此时[local.1]就露出了他真面目[ebp-4]

第一章的时候我们讲到了,mov(move)数据传送指令

mov a,b 把b的值传给a

当然mov也可以对内存中的数据进行赋值

这里面 mov [ebp-4],0x0 就是把0赋值给内存中所设置的变量,其中[]操作符可以引用内存中的数据

类似于源码中

call指令就是调用,那就是调用printf函数输出”PleaseInput Flag Number”这个字符串指针

lea eax,dword ptrss:[ebp-0x4]

LEA指令是一个计算机指令,可以将有效地址传送到指定的的寄存器。

按道理来说就把变量1的地址传递给了eax寄存器

push eax

push Text.00EE3E50

现在的eax其实被传递了变量1的地址

往下面一瞥会发现scanf函数

下面是scanf函数的定义

int scanf(const char * restrict format,...);

一般代码中都是scanf(“格式说明符”,&变量地址)

这里面格式说明符是函数的参数1,变量地址是函数的参数2

而这个变量地址就类似于图中的push eax-> 参数2

而格式说明符就类似于图中的pushText.00EE3E50 ->参数1

那为何是先把参数2推入,再把参数1推入呢?

比如 int Text(a,b,c)这个函数Text参数为a,b,c

在Windows调用规定中

这个函数在汇编中会

Push c

Push b

Push a

Call Text函数的地址

在此你应该能发现参数啊a,b,c却被反向以c,b,a的顺序压入栈中,然后再callText函数的地址

Call指令当然就是调用scanf函数读取输入flag的值

Add esp,0xc

由于_cdcel调用约定,故需要进行堆栈平衡

cmp dword ptrss:[ebp-0x4],0x2F59

cmp是比较指令 而这里面比较的两个对象是变量1与0x2F9(12121)

故cmp指令可以影响标志寄存器

Jnz short Text.009E1036

Jnz跳转指令,由于前面的cmp指令

若变量1-12121=0         Z位=1    jnz不跳转

若变量1-12121!=0        Z位=0    jnz跳转到009E1036

那这个程序的大致流程就是输入变量1的数以后与12121做比较,如果两个数相等,Z位=1 ,jnz不跳转,输入Right!;如果两个数不相等,Z位=0,jnz跳转到009E1036上,输出Error!

然后剩下的代码分析和前面所讲的差不多,大家可以自己写一下注释

00x02总结

本篇我们介绍如何用OD来分析一个简单的程序,同学可以在事后自己用OD跑一下,这样会理解的更加深刻

下一章 如何用OD(OllyDbg)动态调试程序

点击“阅读原文”即可下载本次文章所用到的几个程序的例子哦~

从零开始的程序逆向之路基础篇 第二章——用OllyDbg(OD)分析一个简单的软件的更多相关文章

  1. 顶级c程序员之路 基础篇 - 第一章 关键字的深度理解 number-1

    c语言有32个关键字,每个关键字你都理解吗? 今天出场的是: auto ,  register,  static,   extern 为什么他们会一起呢,说到这里不得不谈到c语言对变量的描述. c给每 ...

  2. Java语言程序设计(基础篇)第二章

    第二章 基本程序设计 2.2 编写简单的程序 1.变量名尽量选择描述性的名字(descriptive name). 2.实数(即带小数点的数字)在计算机中使用一种浮点的方法来表示.因此,实数也称为浮点 ...

  3. 从零开始的程序逆向之路 第一章——认识OD(Ollydbg)以及常用汇编扫盲

    作者:Crazyman_Army 原文来自:https://bbs.ichunqiu.com/thread-43041-1-1.html 0×00 序言: 1.自从上次笔者调戏完盗取文件密码大黑客后, ...

  4. Java编程基础篇第二章

    关键字 概述:被Java语言赋予特定含义的单词. 特点:组成关键字的字母全部为小写字母. 标识符 概述:给类,接口,包,方法,常量起名字时的字符序列 组成规则:英文大小写字母,数字,$和— 命名规则. ...

  5. 编写高质量代码:改善Java程序的151个建议(第二章:基本类型)

    编写高质量代码:改善Java程序的151个建议(第二章:基本类型) 目录 建议21:用偶判断,不用奇判断 建议22:用整数类型处理货币 建议23:不要让类型默默转换 建议24:边界还是边界 建议25: ...

  6. ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局

    本文转自 :http://www.cnblogs.com/wendingding/p/3761730.html ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布 ...

  7. iOS开发UI篇—使用picker View控件完成一个简单的选餐应用

    iOS开发UI篇—使用picker View控件完成一个简单的选餐应用 一.实现效果 说明:点击随机按钮,能够自动选取,下方数据自动刷新. 二.实现思路 1.picker view的有默认高度为162 ...

  8. python之路基础篇

    基础篇 1.Python基础之初识python 2.Python数据类型之字符串 3.Python数据类型之列表 4.Python数据类型之元祖 5.Python数据类型之字典 6.Python Se ...

  9. python学习之路基础篇(第四篇)

    一.课程内容回顾 1.python基础 2.基本数据类型  (str|list|dict|tuple) 3.将字符串“老男人”转换成utf-8 s = "老男人" ret = by ...

随机推荐

  1. 学习node.js 第1篇 介绍nodejs

    Node.js是什么? Node.js是建立在谷歌Chrome的JavaScript引擎(V8引擎)的Web应用程序框架. 它的最新版本是:v0.12.7(在编写本教程时的版本).Node.js在官方 ...

  2. 通过jquery 获取用户当前所在的城市名称和IP地址

    下面这段JS代码是通过jquery 结合新浪IP地址库和QQip地址库接口获取用户当前所在的城市(省份)名称. 用户当前IP地址等数据.其中当前IP是通过 QQip地址库接口获取,其他数据都是通过 新 ...

  3. cmake find_package 中,include_directories,target_link_libraries 的值怎么知道?

    拿Sophus库为例: find_package(Sophus REQUIRED) include_directories(${Sophus_INCLUDE_DIRS}) target_link_li ...

  4. mobilenet之Depthwise +Pointwise

    我们知道,mobilenet是适用于移动端的深度学习网络,主要优点是参数少.模型小.准确率相比一些传统卷积损失少等特点. mobileNet之所以这么ok,是因为引入了Depthwise +Point ...

  5. TensorFlow Android Camera Demo 使用android studio编译安装和解决Execution failed for task ':buildNativeBazel'报错

    可以参考官网:https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#android-stud ...

  6. 使用requests抓取https报SSL错误

    安装requests的方法:sudo pip install requests 当碰到requests链接https的时候报SSL错误的时候使用如下解决: 1:将python的pip 版本升级到9.0 ...

  7. 735. Asteroid Collision彗星相撞后的消失数组

    [抄题]: We are given an array asteroids of integers representing asteroids in a row. For each asteroid ...

  8. 48- java Arrays.sort和collections.sort()再次总结

    今天又碰到一个新BUG,记下来. 一直报空指针异常,我就很奇怪了,怎么就空指针了呢,我输出时,也能输出东西呀. 原来Arrays.sort() 和 Collections.sort() 都是对整个数组 ...

  9. 给 Chrome浏览器 添加 Javascript小书签,查看当前页面全部加载的javascript文件及代码片段

    小书签又名 Bookmarklet,由英文单词 Bookmark 和 Applet 组合而来.简单地说,小书签就是把一段带有特定功能的 JavaScript 代码保存至收藏夹,当你需要的时候点击它来实 ...

  10. 远程连接centos6.5

    安装上传下载工具: 直接yum -y install lrzsz 下载数据到本地下载目录:sz filename1 filename2 … 上传数据到远程:执行rz –be 命令,客户端会弹出上传窗口 ...