一个PE文件的逆向分析

idf-ctf上有个题,是PE文件的逆向,反正对我来说做出来就是有意思的题,做不出来就没劲。言归正传,下面看一下吧

大家想玩可以去这个地方去拿题http://pan.baidu.com/s/1dDzUL0X

然后,上次说到了IDA的F5插件,是的,很牛。之前不用是因为太菜,不会。。。。。。然后这次用了下,果然神器,所以最近也很有必要学一学IDA的东西,推荐大家看《IDA Pro权威指南》。

好的吧,先把文件拖peid,没壳。然后拖OD,捣啊捣,脑袋大,下断点啊啥的,反正就是弄的很烦,就换IDA了,不过OD查了下字符串,还是得到了一些信息的

拉到IDA先看看吧,

有点晕,看看代码吧

.text:0041148B                 mov     esi, esp
.text:0041148D push offset Format ; "plz enter the flag:"
.text:00411492 call ds:printf
.text:00411498 add esp, 4
.text:0041149B cmp esi, esp
.text:0041149D call sub_411136

很好,看到了熟悉的字符串往下拉就是对和错的字符串。

push    offset asc_415764 ; "\r\n"
.text:004115E1 call ds:printf
.text:004115E7 add esp, 4
.text:004115EA cmp esi, esp
.text:004115EC call sub_411136
.text:004115F1 cmp [ebp+var_C0], 0
.text:004115F8 jnz short loc_411613
.text:004115FA mov esi, esp
.text:004115FC push offset aURRight ; "u r right!\r\n"
//正确喽
.text:00411601 call ds:printf
.text:00411607 add esp, 4
.text:0041160A cmp esi, esp
.text:0041160C call sub_411136
.text:00411611 jmp short loc_41162F
.text:00411613 ; ---------------------------------------------------------------------------
.text:00411613
.text:00411613 loc_411613: ; CODE XREF: sub_4113A0+258j
.text:00411613 mov esi, esp
.text:00411615 push offset aURWrong ; "u r wrong\r\n\r\n"
//错误啊
.text:0041161A call ds:printf
.text:00411620 add esp, 4
.text:00411623 cmp esi, esp
.text:00411625 call sub_411136
.text:0041162A call sub_41113B

但是吧,这个有点看着头疼,于是想到了之前说过的F5大法,按了一下F5就出现了以下情况。

c语言啊。。。。随后看了下这F5插件的相关资料,原来需要在对应函数区域才管用,所以这就是为啥上次我按死了也没用的原因。

不对,刚刚又出了个问题,X86版本的才能对该程序F5,我刚打开的是X64,所以这个也得注意。

int sub_4113A0()
{
int v1; // [sp+Ch] [bp-194h]@1
int i; // [sp+D4h] [bp-CCh]@8
int v3; // [sp+E0h] [bp-C0h]@8
int v4; // [sp+ECh] [bp-B4h]@1
int v5; // [sp+F0h] [bp-B0h]@1
int v6; // [sp+F4h] [bp-ACh]@1
int v7; // [sp+F8h] [bp-A8h]@1
int v8; // [sp+FCh] [bp-A4h]@1
int v9; // [sp+100h] [bp-A0h]@1
int v10; // [sp+104h] [bp-9Ch]@1
int v11; // [sp+108h] [bp-98h]@1
int v12; // [sp+10Ch] [bp-94h]@1
int v13; // [sp+110h] [bp-90h]@1
int v14; // [sp+114h] [bp-8Ch]@1
int v15; // [sp+118h] [bp-88h]@1
int v16; // [sp+11Ch] [bp-84h]@1
int v17; // [sp+120h] [bp-80h]@1
int v18; // [sp+124h] [bp-7Ch]@1
int v19; // [sp+128h] [bp-78h]@1
int v20; // [sp+12Ch] [bp-74h]@1
int v21; // [sp+130h] [bp-70h]@1
int v22; // [sp+134h] [bp-6Ch]@1
int v23; // [sp+138h] [bp-68h]@1
int v24; // [sp+13Ch] [bp-64h]@1
int v25; // [sp+140h] [bp-60h]@1
char v26; // [sp+14Fh] [bp-51h]@1
char v27[17]; // [sp+178h] [bp-28h]@2 //一个数组啊
char v28; // [sp+189h] [bp-17h]@13
char v29; // [sp+18Ah] [bp-16h]@14
char v30; // [sp+18Bh] [bp-15h]@15
char v31; // [sp+18Ch] [bp-14h]@16
char v32; // [sp+18Dh] [bp-13h]@17
unsigned int v33; // [sp+19Ch] [bp-4h]@1
int savedregs; // [sp+1A0h] [bp+0h]@1 memset(&v1, 0xCCu, 0x194u);
v33 = (unsigned int)&savedregs ^ dword_417000;
v26 = 0;
v4 = 1;
v5 = 4;
v6 = 14;
v7 = 10;
v8 = 5;
v9 = 36;
v10 = 23;
v11 = 42;
v12 = 13;
v13 = 19;
v14 = 28;
v15 = 13;
v16 = 27;
v17 = 39;
v18 = 48;
v19 = 41;
v20 = 42;
v21 = 26;
v22 = 20;
v23 = 59;
v24 = 4;
v25 = 0; //为啥定义那么多?
printf("plz enter the flag:");
sub_411136();
while ( 1 )
{
getch(); //这应该是获取输入的
v1 = sub_411136();
v27[v26] = v1;
if ( !(_BYTE)v1 || v27[v26] == 13 )
break;
if ( v27[v26] == 8 )
{
printf("\b\b");
sub_411136();
--v26;
}
else
{
printf("%c", v27[v26]);
sub_411136();
++v26;
}
}
v3 = 0;
for ( i = 0; i < 17; ++i )
{
if ( v27[i] != byte_415768[*(&v4 + i)] )
v3 = 1;
}
if ( v28 != 49 || v29 != 48 || v30 != 50 || v31 != 52 || v32 != 125 )
v3 = 1;
v27[v26] = 0;
printf("\r\n");
sub_411136();
if ( v3 ) //这边输出判断是以v3为标志的
{
printf("u r wrong\r\n\r\n");
sub_411136();
sub_41113B();
}
else
{
printf("u r right!\r\n");
sub_411136();
}
system("pause");
sub_411136();
sub_411082(&savedregs, &dword_411678);
sub_411014(v1);
return sub_411136();
}

首先,我们看到咱们的输出是以v3为标志的,所以需要看下v3的值是如何变化的。

以上有两个地方对v3进行了修改,要想得到right,必须是的v3为0。因此上面讲v3改成1的操作都应该避开,来看一下紧挨着的上面的语句。

这是一个if的判断语句,是v28是否为49/48/50/52/125,如果不是则v3置1,查找ascll码表,我们可以看到,对应的是“1024}”这几个字符,和预想的一样,因为这个题是ctf题,而出题方给的答题要求是wctf{}格式,因此这应该就是结尾。

再继续往上看,for循环一共17轮,核心语句是v27[i] != byte_415768[*(&v4 + i)],其中v27是一个数组,备注写了。byte_415768[]应该也是个数组,我们跟到定义位置看一下。

 byte_415768     db 73h                  ; DATA XREF: sub_4113A0+1E3r
aWfxcGdvFwfctsl db 'wfxc{gdv}fwfctslydRddoepsckaNDMSRITPNsmr1_=2cdsef66246087138',0

一长条的字符串,先不管它,看[]里面的,这是个指针,取v4地址后加i后为一个地址然后取该地址的内容作为数组的标号。

再查看上面的定义

  v4 = 1;    //w
v5 = 4; //c
v6 = 14; //t
v7 = 10; //f
v8 = 5; //{
v9 = 36; //P
v10 = 23; //e
v11 = 42; //_
v12 = 13; //c
v13 = 19; //R
v14 = 28; //a
v15 = 13; //c
v16 = 27; //k
v17 = 39; //m
v18 = 48; //e
v19 = 41; //1
v20 = 42; //_
v21 = 26;
v22 = 20;
v23 = 59;
v24 = 4;
v25 = 0;

对照该表依次查找,所查找的内容是之前那个字符串的内容,对应找到后内容请看上面的备注,我们只需关注前17个,因为只循环了17轮。

结合上面,我们初步得出结果wctf{Pe_cRackme1_1024},验证了一下,没有问题。

总觉得有一点点小问题,没有想明白,可能脑子短路了吧,问题就是,这个字符数组[]中是1的情况下应该取得是字符数组中第二个字符,也就是答案是以c为开头,后面每个字符都后挪以为。但是根据出题人意思,开头肯定是wctf形式,不是很明白,也可能我C的一些基本功不牢,求指正啊?

一个PE文件的逆向分析的更多相关文章

  1. 一个QQ木马的逆向分析浅谈(附带源码)

    程序流程:首先注册自己程序的窗口以及类等一系列窗口操作,安装了一个定时器,间隔为100ms,功能搜索QQ的类名,如果找到就利用FindWindow("5B3838F5-0C81-46D9-A ...

  2. PE文件学习系列二 DOS头分析

    合肥程序员群:49313181.    合肥实名程序员群 :128131462 (不愿透露姓名和信息者勿加入)Q  Q:408365330     E-Mail:egojit@qq.com PE文件结 ...

  3. 病毒木马查杀实战第016篇:U盘病毒之逆向分析

    比对脱壳前后的程序 我们这次所要研究的是经过上次的脱壳操作之后,所获取的无壳病毒样本.其实我们这里可以先进行一下对比,看看有壳与无壳的反汇编代码的区别.首先用IDA Pro载入原始病毒样本: 图1 可 ...

  4. 手写PE文件(二)

    [文章标题]: 纯手工编写的PE可执行程序 [文章作者]: Kinney [作者邮箱]: mohen_ng@sina.cn [下载地址]: 自己搜索下载 [使用工具]: C32 [操作平台]: win ...

  5. PE文件详解(七)

    本文转载自小甲鱼PE文件讲解系列原文传送门 这次主要说明导出表,导出表一般记录着文件中函数的地址等相关信息,供其他程序调用,常见的.exe文件中一般不存在导出表,导出表更多的是存在于dll文件中.一般 ...

  6. [工控安全]西门子S7-400 PLC固件逆向分析(一)

    不算前言的前言:拖了这么久,才发现这个专题没有想象中的简单,学习的路径大致是Step7->S7comm->MC7 code->firmware,我会用尽量简短的语言把前两部分讲清楚, ...

  7. C++PE文件格式解析类(轻松制作自己的PE文件解析器)

    PE是Portable Executable File Format(可移植的运行体)简写,它是眼下Windows平台上的主流可运行文件格式. PE文件里包括的内容非常多,详细我就不在这解释了,有兴趣 ...

  8. [转] 一个U盘病毒简单分析

    (转自:一个U盘病毒简单分析 - 瑞星网   原文日期:2014.03.25) U盘这个移动存储设备由于体积小.容量大.便于携带等优点,给人们的存储数据带来了很大的便利.但正是由于这种便利,也给病毒有 ...

  9. PE文件的执行顺序

    当一个PE文件被执行时,PE装载器首先检查DOS MZ header里的PE header的偏移量.如果找到,则直接跳转到PE header的位置. 当PE装载器跳转到PE header后,第二步要做 ...

随机推荐

  1. Oracle里 用sql*plus 登陆时,用户名和密码是多少啊?

    Oracle里sql*plus的用户名即system用户,密码是自己设置的密码. 如果密码忘记,可通过如下方法重置. 1.win键+R键,输入cmd,打开命令提示符. 2.输入sqlplus /nol ...

  2. sql数据库中如何根据身份证号判断性别

    身份证号有15位和18位的..在sql中该如何判断? I_sex ,) ,) then '男' else '女' END

  3. Docker 使用指南 (三)—— 网络配置

    版权声明:本文由田飞雨原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/95 来源:腾云阁 https://www.qclou ...

  4. WEB安全第七篇--终结篇考验逻辑思维:逻辑漏洞大汇总(越权、会话逻辑、业务逻辑、暴力破解)

    零.前言 最近做专心web安全有一段时间了,但是目测后面的活会有些复杂,涉及到更多的中间件.底层安全.漏洞研究与安全建设等越来越复杂的东东,所以在这里想写一个系列关于web安全基础以及一些讨巧的pay ...

  5. 配置linux DNS

    DNS服务器地址配置 在Linux下面,有一个默认的DNS服务器地址配置文件的设置,存放在 /etc/resolv.conf 设置方法很简单,通过编辑 vi /etc/resolv.conf 设置首选 ...

  6. 关于Properties的用法的详细解释

    如果不熟悉 java.util.Properties类,那么现在告诉您它是用来在一个文件中存储键-值对的,其中键和值是用等号分隔的.(如清单 1 所示).最近更新的java.util.Properti ...

  7. Scala面向对象和模式匹配

    我们要封装数据,定义模板等操作,所以我们需要面向对象. 一.scala中的单例对象 在scala当中,是没有static的,scala给我们提供了单例模式的实现方法.就是使用关键字object. st ...

  8. Python开发【笔记】:sort排序大法

    浅谈排序 程序中经常用到排序函数,Python 提供了 sort 和 sorted 函数,一个原地排序,一个返回排序后的新结果 1.参数 函数原型: sort([cmp[, key[, reverse ...

  9. Keras-在预训练好网络模型上进行fine-tune

    在深度学习的学习过程中,可能会用到一些已经训练好的模型,比如Alex Net,google Net,VGG,Resnet等,那我们怎样对这些训练好的模型进行fine-tune来提高准确率呢? 参考文章 ...

  10. 测试命令运行时间:timeit和profile

    先说timeit from timeit import Timer def test1(): n=0 for i in range(101): n+=i return n def test2(): r ...