IDA入门笔记

 

  题目来源

    南邮CTF :: RE :: Hello,RE(应该是)

    XDUCTF :: ??? :: ????????(不知道不知道不知道)

    

    总而言之我会在百度网盘再上传一份: >>百度网盘, 提取码 3dcv <<

 


 0> 总结

  1> 查看.exe是32位还是64位的: notepad++打开,Ctrl-F找"PE", 若位PE……L则为32位,若为PE……d则为64位。

  2> IDApro常用快捷键: 

 

    1> F5 : 嘿嘿嘿

    2> R : 将看不懂的数据转化为可能看懂的数据

    3> Y : 修改变量/函数类型

    4> N : 修改变量/函数名

    5> X : 查看变量/函数被引用情况

    6> U : 将此处还原到初始状态

    7> D : 在汇编语言界面,改变数据类型

    8> TAB : 切换显示形式 ……(待续)

    9> F2 : 设置断点

    10> G : 动态调试界面,跳转到目标地址

 

  3> 常规操作:

    1> 修参数:名称 && 类型 

    2> 动态调试:断点 && 栈 

 

1> 准备

  操作系统:windows   //建议win7或以上

  IDA  //可以去"吾爱破解"论坛自行下载。

  C语言编译器 或者 IDA的插件 "Lazy IDA"  //由于当时没时间配置LazyIDA,所以一些步骤只好自己写。

  notepad++  //官网传送门

 

2> 0.exe

  1> 用Notepad++打开0.exe,发现"PE @#$%^&*( L ", 说明这个可执行文件是32位的。  //若为"PE!@#$%^&*()  d" ,则说明是64位的。

  IDA入门笔记_第1张图片

 

  2> 拖到idaq(32位)里,一路ok

  IDA入门笔记_第2张图片

 

  3> 选中_main函数,F5

  IDA入门笔记_第3张图片

 

  4> 选中v5等的那些数字,按R,就可以把她们变为可以阅读的文字。

  IDA入门笔记_第4张图片

 

  5> 显然这就是每一小节倒置后的flag,可以手动敲出来。

    不过,由于是用strcmp函数比较输入数据和答案是否匹配,我们还可以尝试动态调试。

 

  6> 在第二步的那个界面里(IDA VIEW-A),选中_strcmp, 摁X看看哪里调用了这个家伙。

  IDA入门笔记_第5张图片

 

  7> 设置断点(F2), 效果如图:

  

 

  8> 在上边的小条条里选中"Local Win32 debugger",按绿色的运行按钮开始动态调试。

  IDA入门笔记_第6张图片

 

  9> 随便输一串啥东西,回车确定。发现不动弹了,这是正常的。

  

 

  10> 在右下角的stack view里我们可以发现两个神奇的地址。

  IDA入门笔记_第7张图片

 

  11> 复制,选中它左边的窗口(Hex View-1),按G跳转到地址,贴进去,OK.

  IDA入门笔记_第8张图片

 

  12> 找到了之前丢进去的东西。

  

 

  13> 那么第二个地址就应该是flag了,如法炮制,GET~

  

 


 

3> 1.exe

  1> 先运行一下。

    发现输入之后闪了一下就推出了,恼火。

 

  2> 不行,恼火,Win+R开cmd,重新运行一次。

  IDA入门笔记_第9张图片

  发现了可以用来定位的字符。

 

  3> notepad打开,是32位的。

  

 

  4> 拖进IDA(32位),发现没有main函数。

    //我起初以为哪个start函数就是主函数,然而盯着屏幕看了几分钟之后我发现我错了。  看不懂

  IDA入门笔记_第10张图片

 

  5> 这时,最开始我们见到的那些文字就有用了。在view--open subviews-strings 里搜索。

  IDA入门笔记_第11张图片

 

  6> 随便点一个好了(双击)

   IDA入门笔记_第12张图片

 

  7> 摁X看引用,OK.

  IDA入门笔记_第13张图片

 

  8> F5,发现sub_401020()就是main

  IDA入门笔记_第14张图片

 

  9> 选中函数名,摁N重命名,改为"main”

 

  10> 我们可以看到主函数干了很多骚操作,乱七八糟的不想看下去。

 

  11> 不过,粗略一读,可以发现sub_401450就是printf,摁N重命名。

 

  12> 在那个带有"flag字样的if语句里",我们可以发现,显示对一个名字叫Str的东西做了sub_4013C0,然后把它和flag格式的头和尾巴作比较。

    

  看看sub_401340,就是exit.

  

  于是我们大胆猜测,sub_4013C0就是scanf,而这个if语句就是在判断输入内容是否符合flag的格式。

  从初中到大学的所有数学证明题,不都是"没原因,但就是知道该这样做" 吗?(啧啧啧)

 

  13> 摁N改名,顿时清晰(了一些)。

  IDA入门笔记_第15张图片

 

  14> 验证的语句是"strcmp",所以改名。

  

 

  15> 小结

    先让用户输入flag,判断是否符合格式,若不符合则退出程序。

    然后把flag去掉格式,复制到DST  //DST即flag{内的内容},暂且重命名为"flag_body"

    再对DST进行sub_4011F0操作(有些复杂,暂不处理)

    之后把DST和v4进行一些奇怪的操作

    最后判断v4是否符合a23g……那个字符串

    如果是,就是。否则退出。

 

  16> 综上所述,再次大胆猜想,

    sub_4011F0和sub_401270是加密算法,

    而a23……是加密后的flag,

    于是,接下来的任务就是看懂加密算法,并写出解密算法。

 

  17> sub_4011F0

    IDA入门笔记_第16张图片

    可以看到,v2本应是int,却显示为char。(虽说根本没啥用就是了)

    而根本不需要返回值,所以我们需要无视和result有关的语句。(有插件,之后有机会补上)

 

    1> 函数,判断了一下函数是否满足一个和32有关的条件,然后再把传入的flag和另一个数组亦或。

      可以发现,flag的长度为32。

 

    2> 双击查看dword4040,很显然这是一个每个元素大小为4B的数组。

    IDA入门笔记_第17张图片

 

    3> 右键,array,将这个家伙转化为数组,32个元素。

    IDA入门笔记_第18张图片

       IDA入门笔记_第19张图片

      

 

    4> 显然,这就是与flag异或的数组。

      XOR的逆运算还是XOR,所以只需要把这玩意转化一下即可。  //转化方法在后面

 

  18> sub_401270

    1> 改变量名(len, i, input, output)

 

    2> 改变量类型(output是个char*)

    IDA入门笔记_第20张图片

 

    3> 可以发现,加密原理是根据"a1"这个东西将输入的顺序调换,从而转化为密文。所以,a1即所谓的"key"

 

    4> 返回main,找到所谓"a1",,双击。

 

    5> 转化为int数组,先如下图操作,然后右键-array,32个元素。  

      1> 按d转化数据类型为dd(即整型)

 

      2> 右键-array -32个元素

      //若误操作,你会发现没有撤销功能,然而可以按U将该单元重置。

 

    6> 先在我们需要转化的两组key就都在这里了。

    IDA入门笔记_第21张图片

 

    7> 然后就可以进行解密操作了。

 

  19> sub_401270的解密算法

    注释:

      0> 伪代码

      1> key2即映射规则,即dword_4040C0

      2> output和input分别是这条函数的输出数据和输入数据。

    加密算法:

for(int i=0; i<32; i++) output[key2[i]] = input[i];

    解密算法:

for(int i=0; i<32; i++) output[i] = input[key2[i]]

 

  20> sub_4011F0的解密算法

    注释:

      0> 伪代码

      1> key1即dword_404040

      2> " ^ "是异或(XOR),逆运算还是异或。

    加密算法:

for(int i=0; i 
   

    解密算法:(同上)

for(int i=0; i 
   

 

  21> 如何将形如"53h"的十六进制数丢进C++   lazy IDA 或者 自己写代码。

    注释:

      1> C++只能识别形如"0x53"的十六进制数而不能识别形如"53h"的十六进制数

      2> 写一段处理字符串的函数即可

      3> 因为懒得写,所以手工处理了一部分。只需把"dd"去掉;把换行符换为" ,"即可。

      3.5> 因为懒得整合,所以把处理key的函数和主函数分开写了。需要手工复制粘贴一下,不过好在代码行数少,DEBUG比较方便。

      4> 代码如下,在程序所在目录下新建in.txt,把东西丢进去,略作处理,保存,运行程序即可。

    手工处理之后的key1:

53h, 45h, 5Ch, 1Eh, 50h, 13h, 2Fh, 78h, 4, 53h, 58h, 4Ah, 43h, 1, 41h, 2Ah, 8, 40h, 67h, 2Fh, 0Ch, 4Ah, 12h, 2Eh, 41h, 6Ch, 5, 54h, 40h, 12h, 5Bh, 4Fh

    手工处理之后的key2:

4, 0Fh, 0Bh, 1Eh, 0Eh, 14h, 1Fh, 9, 17h, 2, 19h, 1Ch, 12h, 10h, 0, 8, 11h, 1, 15h, 3, 0Ah, 1Dh, 0Ch, 16h, 18h, 0Dh, 1Bh, 5, 7, 6, 13h, 1Ah

 

    代码:

#include
#include
int main() {
    freopen("out2.txt", "w", stdout);
    char ans[41] = "23gjf13au98hk3a1090zp8qjs41h39jp";
    char flag[41];
    int key2[41] = {0x4, 0x0F, 0x0B, 0x1E, 0x0E, 0x14, \
0x1F, 0x9, 0x17, 0x2, 0x19, 0x1C, 0x12, 0x10, 0x0, 0x8, \
0x11, 0x1, 0x15, 0x3, 0x0A, 0x1D, 0x0C, 0x16, 0x18, 0x0D, \
0x1B, 0x5, 0x7, 0x6, 0x13, 0x1A};
      int key1[41] = {0x53, 0x45, 0x5C, 0x1E, 0x50, 0x13, \
0x2F, 0x78, 0x4, 0x53, 0x58, 0x4A, 0x43, 0x1, 0x41, 0x2A, \
0x8, 0x40, 0x67, 0x2F, 0x0C, 0x4A, 0x12, 0x2E, 0x41, 0x6C, \
0x5, 0x54, 0x40, 0x12, 0x5B, 0x4F};
    for(int i=0; i<32; i++) {
        flag[i] = ans[key2[i]];
    }
    for(int i=0; i<32; i++) {
        flag[i] ^= key1[i];
    }
    printf("%s\n", flag);
    fclose(stdout);
    system("out2.txt");
    return 0;
}

 

  22> 整合,运算:

    注释:

      1> flag:原程序的输入数据,同时也是本程序的输出数据

      2> ans:本程序的输入数据,同时也是原程序的输出数据

      3> 运行即可,自动弹出盛放有flag的txt

    代码:

#include
#include
using namespace std;
int main() {
    freopen("out2.txt", "w", stdout);
    char ans[41] = "23gjf13au98hk3a1090zp8qjs41h39jp";
    char flag[41];
    int key2[41] = {0x4, 0x0F, 0x0B, 0x1E, 0x0E, 0x14, \
0x1F, 0x9, 0x17, 0x2, 0x19, 0x1C, 0x12, 0x10, 0x0, 0x8, \
0x11, 0x1, 0x15, 0x3, 0x0A, 0x1D, 0x0C, 0x16, 0x18, 0x0D, \
0x1B, 0x5, 0x7, 0x6, 0x13, 0x1A};
      int key1[41] = {0x53, 0x45, 0x5C, 0x1E, 0x50, 0x13, \
0x2F, 0x78, 0x4, 0x53, 0x58, 0x4A, 0x43, 0x1, 0x41, 0x2A, \
0x8, 0x40, 0x67, 0x2F, 0x0C, 0x4A, 0x12, 0x2E, 0x41, 0x6C, \
0x5, 0x54, 0x40, 0x12, 0x5B, 0x4F};
    for(int i=0; i<32; i++) {
        flag[i] = ans[key2[i]];
    }
    for(int i=0; i<32; i++) {
        flag[i] ^= key1[i];
    }
    flag[32] = '\0';
    printf("%s\n", flag);
    fclose(stdout);
    system("out2.txt");
    return 0;
}

 

    运行结果:

    IDA入门笔记_第22张图片

    即:

     flag{5t4t1c_An4lys1s_1s_E4sy_2_me!!!~} 

 

 

 

 

 

 

 

 

 

    

 

转载于:https://www.cnblogs.com/iishuu/p/10294740.html

你可能感兴趣的:(IDA入门笔记)