idf-ctf上有个题,是PE文件的逆向,反正对我来讲作出来就是有意思的题,作不出来就没劲。言归正传,下面看一下吧数组
你们想玩能够去这个地方去拿题http://pan.baidu.com/s/1dDzUL0X函数
而后,上次说到了IDA的F5插件,是的,很牛。以前不用是由于太菜,不会。。。。。。而后此次用了下,果真神器,因此最近也颇有必要学一学IDA的东西,推荐你们看《IDA Pro权威指南》。插件
好的吧,先把文件拖peid,没壳。而后拖OD,捣啊捣,脑壳大,下断点啊啥的,反正就是弄的很烦,就换IDA了,不过OD查了下字符串,仍是获得了一些信息的3d
拉到IDA先看看吧,指针
有点晕,看看代码吧code
.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
很好,看到了熟悉的字符串往下拉就是对和错的字符串。orm
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就出现了如下状况。blog
c语言啊。。。。随后看了下这F5插件的相关资料,原来须要在对应函数区域才管用,因此这就是为啥上次我按死了也没用的缘由。v8
不对,刚刚又出了个问题,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的一些基本功不牢,求指正啊?