题目来源

    南邮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位的。

  

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

  

  3> 选中_main函数,F5

  

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

  

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

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

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

  

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

  

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

  

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

  

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

  

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

  

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

  

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

  


3> 1.exe

  1> 先运行一下。

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

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

  

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

  3> notepad打开,是32位的。

  

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

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

  

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

  

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

  

  7> 摁X看引用,OK.

  

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

  

  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改名,顿时清晰(了一些)。

  

  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

    

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

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

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

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

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

    

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

    

       

      

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

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

  18> sub_401270

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

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

    

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

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

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

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

      2> 右键-array -32个元素

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

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

    

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

  19> sub_401270的解密算法

    注释:

      0> 伪代码

      1> key2即映射规则,即dword_4040C0

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

    加密算法:

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

    解密算法:

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

  20> sub_4011F0的解密算法

    注释:

      0> 伪代码

      1> key1即dword_404040

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

    加密算法:

for(int i=; i<len; i++) flag[i] ^= key1[i];

    解密算法:(同上)

for(int i=; i<len; i++) flag[i] ^= key1[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, , 53h, 58h, 4Ah, 43h, , 41h, 2Ah, , 40h, 67h, 2Fh, 0Ch, 4Ah, 12h, 2Eh, 41h, 6Ch, , 54h, 40h, 12h, 5Bh, 4Fh

    手工处理之后的key2:

, 0Fh, 0Bh, 1Eh, 0Eh, 14h, 1Fh, , 17h, , 19h, 1Ch, 12h, 10h, , , 11h, , 15h, , 0Ah, 1Dh, 0Ch, 16h, 18h, 0Dh, 1Bh, , , , 13h, 1Ah

    代码:

#include<cstdio>
#include<cstdlib>
int main() {
freopen("out2.txt", "w", stdout);
char ans[] = "23gjf13au98hk3a1090zp8qjs41h39jp";
char flag[];
int key2[] = {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[] = {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=; i<; i++) {
flag[i] = ans[key2[i]];
}
for(int i=; i<; i++) {
flag[i] ^= key1[i];
}
printf("%s\n", flag);
fclose(stdout);
system("out2.txt");
return ;
}

  22> 整合,运算:

    注释:

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

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

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

    代码:

#include<cstdio>
#include<cstdlib>
using namespace std;
int main() {
freopen("out2.txt", "w", stdout);
char ans[] = "23gjf13au98hk3a1090zp8qjs41h39jp";
char flag[];
int key2[] = {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[] = {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=; i<; i++) {
flag[i] = ans[key2[i]];
}
for(int i=; i<; i++) {
flag[i] ^= key1[i];
}
flag[] = '\0';
printf("%s\n", flag);
fclose(stdout);
system("out2.txt");
return ;
}

    运行结果:

    

    即:

     flag{5t4t1c_An4lys1s_1s_E4sy_2_me!!!~}

    

IDA入门笔记的更多相关文章

  1. 每天成长一点---WEB前端学习入门笔记

    WEB前端学习入门笔记 从今天开始,本人就要学习WEB前端了. 经过老师的建议,说到他每天都会记录下来新的知识点,每天都是在围绕着这些问题来度过,很有必要每天抽出半个小时来写一个知识总结,及时对一天工 ...

  2. ES6入门笔记

    ES6入门笔记 02 Let&Const.md 增加了块级作用域. 常量 避免了变量提升 03 变量的解构赋值.md var [a, b, c] = [1, 2, 3]; var [[a,d] ...

  3. [Java入门笔记] 面向对象编程基础(二):方法详解

    什么是方法? 简介 在上一篇的blog中,我们知道了方法是类中的一个组成部分,是类或对象的行为特征的抽象. 无论是从语法和功能上来看,方法都有点类似与函数.但是,方法与传统的函数还是有着不同之处: 在 ...

  4. React.js入门笔记

    # React.js入门笔记 核心提示 这是本人学习react.js的第一篇入门笔记,估计也会是该系列涵盖内容最多的笔记,主要内容来自英文官方文档的快速上手部分和阮一峰博客教程.当然,还有我自己尝试的 ...

  5. redis入门笔记(2)

    redis入门笔记(2) 上篇文章介绍了redis的基本情况和支持的数据类型,本篇文章将介绍redis持久化.主从复制.简单的事务支持及发布订阅功能. 持久化 •redis是一个支持持久化的内存数据库 ...

  6. redis入门笔记(1)

    redis入门笔记(1) 1. Redis 简介 •Redis是一款开源的.高性能的键-值存储(key-value store).它常被称作是一款数据结构服务器(data structure serv ...

  7. OpenGLES入门笔记四

    原文参考地址:http://www.cnblogs.com/zilongshanren/archive/2011/08/08/2131019.html 一.编译Vertex Shaders和Fragm ...

  8. OpenGLES入门笔记三

    在入门笔记一中比较详细的介绍了顶点着色器和片面着色器. 在入门笔记二中讲解了简单的创建OpenGL场景流程的实现,但是如果在场景中渲染任何一种几何图形,还是需要入门笔记一中的知识:Vertex Sha ...

  9. unity入门笔记

    我于2010年4月1日硕士毕业加入完美时空, 至今5年整.刚刚从一家公司的微端(就是端游技术+页游思想, 具体点就是c++开发, directX渲染, 资源采取所需才会下载)项目的前端主程职位离职, ...

随机推荐

  1. 20145203盖泽双《Java程序设计》第三周学习总结

    20145203盖泽双<Java程序设计>第三周学习总结 教材学习内容总结 1.两个基本的标准类:java.util.Scanner与java.math.BigDecimal. 2.Big ...

  2. 错误检查roswtf

    准备 在你开始本教程之前请确保roscore没在运行. 安装检查 roswtf 可以检查你的ROS系统并尝试发现问题,我们来试看: $ roscd $ roswtf 你应该会看到(各种详细的输出信息) ...

  3. [图解tensorflow源码] Graph 图构建 (Graph Constructor)

  4. summery 总结篇 访问对象属性的方法

    访问一个对象的属性有两种方法: (1),通过“.”来访问:object.propertyName; (2),通过[]来访问:object[propertyName]; 访问一个对象的方法只能通过“.” ...

  5. ABAP-DBC录屏

    *&---------------------------------------------------------------------**& ZXXL_MM02_01*& ...

  6. 腾讯云Mac图床插件

    背景 随着博客越写越多,难免会遇到需要插入图片来说明的情况. 图床选择 首先调研了市面上的图床服务,本着稳定长期的目标,过滤掉了打一枪换一个地方的野鸡小网站,剩余比较靠谱的优缺点如下. 图床 优点 缺 ...

  7. redis 基本数据类型-字符串(String)

    不瘦原来对redis也是有个大概的了解(就你知道的多), 但是最近和大神聊天的过程中才明白自己知道的简直就是鸡毛蒜皮(让你得瑟),所以不瘦打算从头在捋一遍,顺便把过程也记录下来,如果能给大家在学习re ...

  8. STM32的AFIO时钟什么时候需要开启

    相比于普通单片机,STM32 拥有复杂的时钟系统,相应的控制器称为 RCC(Reset Clock Controller,复位与时钟控制器).每个外设都配备了外设时钟的开关,当我们不使用某个外设时,可 ...

  9. sqlserver 索引优化 CPU占用过高 执行分析 服务器检查

    原文:sqlserver 索引优化 CPU占用过高 执行分析 服务器检查 1. 管理公司一台服务器,上面放的东西挺多的.有一天有个哥们告诉我现在程序卡的厉害.我给他说,是时候读点优化的书了.别一天到晚 ...

  10. JavaScript总结(三)

    如何执行代码语句? 使用函数,函数是一组可以随时随地运行的语句,它们是JavaScript的核心.函数是由关键字function.函数名加一组参数以及置于括号中要执行的代码声明的.语法如下: Func ...