练习IDA两年半

打开尘封已久的bugku,从题目中练习使用,现在都已经是新版本了 orz

入门逆向

运行baby.exe

将解压后的baby.exe拖到IDA里面

主函数中找到mov指令 可以看到这里就是flag

flag{Re_1s_S0_C0OL}

signin

下载附件

解压之后是sign_in.apk ,Android逆向我不会啊orz
丢到AndroidKiller 里面去
可以看到这里有一个checkpassword方法

不过我不知道怎么把这个直接跳过 估计是需要登录的时候直接绕过这个方法然后重打包
看到评论里面有的人用的是GDK https://github.com/charles2gan/GDA-android-reversing-Tool

GDA,一款用C++实现的强大的Dalvik字节码反编译器,具有分析速度快、内存磁盘消耗低等优点,对apk、dex、odex、oat、jar、class、aar文件的反编译能力更强。

GDK打开之后 牛逼啊

登录验证逻辑如下

private String getFlag(){
return this.getBaseContext().getString(0x7f0b0020);
}
private void showMsgToast(String p0){
Toast.makeText(this, p0, 1).show();
}
public void checkPassword(String p0){
if (p0.equals(new String(Base64.decode(this.getFlag().reverse(), 0)))) {
this.showMsgToast("Congratulations !");
}else {
this.showMsgToast("Try again.");
}
return;
}

接下来去找这个0x7f0b0020对应的值是多少
转换成十进制为

去找2131427360 这玩意,不过我直接搜索这个值找不到
手动查toString 看到在这里

所以这个值对应的是toString
GDK用起来卡卡的
toString 的值为 991YiZWOz81ZhFjZfJXdwk3X1k2XzIXZIt3ZhxmZ

按照规则 把字符串逆序 ZmxhZ3tIZXIzX2k1X3kwdXJfZjFhZ18zOWZiY199
然后base64解密,得到flag
flag{Her3_i5_y0ur_f1ag_39fbc_}

Easy_Re


额要是我知道我还运行干啥
我理解这里应该是会有一个比较操作 逆向的时候在比较操作的时候看flag值
IDA打开之后F5查看伪代码

输入的内容存储到v7变量中 然后跟v5进行对比,对比结果存储到v3中

scanf("%s", v7);
v3 = strcmp(v5.m128i_i8, v7);

所以真实的flag就在v5中,赋值操作在

v5 = _mm_loadu_si128((const __m128i *)&xmmword_413E34);

真实值在 xmmword_413E34,点击跟进

按 a 转译

获取flag

游戏过关

运行exe,看起来这个游戏好难

n是灯的序列号,m是灯的状态
如果第N个灯的m为1,则它点亮,否则它熄灭
起初所有的灯都关上了
现在你可以输入n来改变它的状态
但你应该注意一件事,如果你改变第N个灯的状态,第(N-1)个和第(N+1)个的状态也会改变
当所有灯亮起时,flag将出现
现在,输入n

乱输一通

获得flag zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}
丢到IDA里面检查一下,这次的文件比较多 搜索flag字符串 alt+t

看到输出flag的界面

汇编代码如下

F5转换为C代码,去除掉一些干扰代码

int sub_45E940()
{
int i; // [esp+D0h] [ebp-94h]
char v2[22]; // [esp+DCh] [ebp-88h] BYREF
char v3[32]; // [esp+F2h] [ebp-72h] BYREF
char v4[4]; // [esp+112h] [ebp-52h] BYREF
char v5[64]; // [esp+120h] [ebp-44h] sub_45A7BE("done!!! the flag is ");
v5[0] = 18;
v5[1] = 64;
v5[2] = 98;
v5[3] = 5;
v5[4] = 2;
v5[5] = 4;
v5[6] = 6;
v5[7] = 3;
v5[8] = 6;
v5[9] = 48;
v5[10] = 49;
v5[11] = 65;
v5[12] = 32;
v5[13] = 12;
v5[14] = 48;
v5[15] = 65;
v5[16] = 31;
v5[17] = 78;
v5[18] = 62;
v5[19] = 32;
v5[20] = 49;
v5[21] = 32;
v5[22] = 1;
v5[23] = 57;
v5[24] = 96;
v5[25] = 3;
v5[26] = 21;
v5[27] = 9;
v5[28] = 4;
v5[29] = 62;
v5[30] = 3;
v5[31] = 5;
v5[32] = 4;
v5[33] = 1;
v5[34] = 2;
v5[35] = 3;
v5[36] = 44;
v5[37] = 65;
v5[38] = 78;
v5[39] = 32;
v5[40] = 16;
v5[41] = 97;
v5[42] = 54;
v5[43] = 16;
v5[44] = 44;
v5[45] = 52;
v5[46] = 32;
v5[47] = 64;
v5[48] = 89;
v5[49] = 45;
v5[50] = 32;
v5[51] = 65;
v5[52] = 15;
v5[53] = 34;
v5[54] = 18;
v5[55] = 16;
v5[56] = 0; qmemcpy(v2, "{ ", 2);
v2[2] = 18;
v2[3] = 98;
v2[4] = 119;
v2[5] = 108;
v2[6] = 65;
v2[7] = 41;
v2[8] = 124;
v2[9] = 80;
v2[10] = 125;
v2[11] = 38;
v2[12] = 124;
v2[13] = 111;
v2[14] = 74;
v2[15] = 49;
v2[16] = 83;
v2[17] = 108;
v2[18] = 94;
v2[19] = 108;
v2[20] = 84;
v2[21] = 6; for ( i = 0; i < 56; ++i )
{
v2[i] ^= v5[i];
v2[i] ^= 0x13u;
}
return sub_45A7BE("%s\n");
}

这里有个问题啊,就是v2和v5的长度不一致

v2的长度就是22,这样的话最后得到的结果是

少了一部分的flag,但是v3和v4的长度加起来是 32+2=34,再加上前面的22就是56,所以我们应该把v2 v3 v4组在一起 为啥这里看不出来 我感觉这里的C语言代码是有点问题
更新python脚本

v2=[123,32,18,98,119,108,65,41,124,80,125,38,124,111,74,49,83,108,94,108,84,6,96,83,44,121,104,110,32,95,117,101,99,123,127,119,96,48,107,71,92,29,81,107,90,85,64,12,43,76,86,13,114,1,117,126,0]
v5=[18,64,98,5,2,4,6,3,6,48,49,65,32,12,48,65,31,78,62,32,49,32,1,57,96,3,21,9,4,62,3,5,4,1,2,3,44,65,78,32,16,97,54,16,44,52,32,64,89,45,32,65,15,34,18,16,0]
flag=""
for i in range(len(v2)):
flag+=chr(v2[i]^v5[i]^0x13) print(flag)

结果如下

换一个方式 使用动态调试 也就是掏出OllyDbg
使用中文搜索引擎

选择智能搜索 然后就可以看到

双击进入

这部分的入栈位置在这里

上转至 006A7AB4

上转调用位置为 006AF66C

这里的几个汇编指令我觉得需要解释一下
可以看到每一个jnz前面都有cmp,也就是比较失败就跳转到 006AF671

如果所有的比较都成功则调用call 方法,调用006A7AB4地址的方法
这里的逻辑很显然就是这里判断灯亮灯灭的判断(IDA中看见

所以我们将这里的jmp地址修改为call地址 不管输入 1-8 的哪个数字都能拿到flag了


右键复制到可执行文件 选择

保存为 ConsoleApplication7.exe,然后运行一下,输入 1,获取flag

Easy_vb

运行之后随便点点 好像没啥用

OD打开智能搜索

树林的小秘密

下载之后我的OD载入不了64位的程序 只能IDA了
shift + F12 搜索flag

看起来是pyinstaller打包的

用对应的工具去恢复源码,工具在这,点进去就是下载
https://nchc.dl.sourceforge.net/project/pyinstallerextractor/dist/pyinstxtractor.py

把工具和待反编译的exe放到一个目录下,然后运行

python pyinstxtractor.py easy_reverse.exe


生成了 easy_reverse.exe_extracted 文件,可以看到反编译的结果为

这里这个没有后缀的就是之前打包的python文件对应的pyc文件
这个时候打开123已经可以拿到flag了,base64解密

Timer(阿里CTF)

又是一个APK
GDA打开 搜索flag

跳转查看,如下

JNI编程?这么上流

这个位置load 了 so文件

所以其实flag在这个里面

但是so文件逆向我更不会了,只能看代码逻辑
初始化onCreate方法

protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
Handler handler = new Handler();
Runnable runnable = new MainActivity$1(this, this.findViewById(0x7f0c0051), this.findViewById(0x7f0c0050), handler);
handler.postDelayed(runnable, 0);
}

运行了这个方法

public void run(){
MainActivity$1 tthis$0;
this.this$0.t = System.currentTimeMillis();
this.this$0.now = (int)(this.this$0.t / 1000);
this.this$0.t = 1500 - (this.this$0.t % 1000);
this.val$tv2.setText("AliCTF");
if (((this.this$0.beg - this.this$0.now)) <= 0) {
this.val$tv1.setText("The flag is:");
this.val$tv2.setText("alictf{"+this.this$0.stringFromJNI2(this.this$0.k)+"}");
}
if (MainActivity.is2((this.this$0.beg - this.this$0.now))) {
tthis$0 = this.this$0;
tthis$0.k = tthis$0.k + 100;
}else {
tthis$0 = this.this$0;
tthis$0.k = tthis$0.k - 1;
}
this.val$tv1.setText("Time Remaining\(s\):"+(this.this$0.beg - this.this$0.now));
this.val$handler.postDelayed(this, this.this$0.t);
return;
}

OK 虽然看起来有点费劲
现在有四个参数

  • t
  • now
  • beg
  • k

now是当前时间戳
beg是启动APK的时候的时间,在

当然加了20万秒 所以如果破解不了的话就等着吧,虽然CTF比赛很快就要结束力
t 是一个取余时间值
k是计算的时间种子,最后会传到JNI方法里面去,所以我们如果直接改if语句是没用的,因为时间种子没有修改正确

所以这里我们有两个地方需要修改,一个是计算出正确的时间种子,一个是进入if语句,先从简单的进入if语句开始

把beg改成0就OK
不过好像GDK没有这个修改重打包的功能,使用AndroidKiller

把if-gtz修改为 if-lez,从判断大于零改为判断小于或等于零
接下来需要计算正确的K,抽离其中的关键因素
使用GDA反编译之后的代码看起来费劲,换成jd-gui
先使用dex2jar 把 classes.dex转换成 jd-gui可识别的jar包

然后使用jd-gui打开jar包,现在看起来就好多了

编写python脚本如下

now=0
beg=0+200000
k=0
def is2(n):
if n<=3:
if n > 1:
return True
return False
elif n%2==0 or n%3==0:
return False
else:
i=5
while i*i <= n:
if 0 == n%i or n%(i+2) == 0:
return False
i=i+6
return True while beg - now > 0:
if is2(beg-now):
k+=100
else:
k-=1
beg -= 1 print(k)

运行得到K值

k值为 1616384
修改代码 在这里直接把K强行赋值

回编译得到修改后的APK

连一下自己手机

adb install之后运行 就可以看到flag了

拿到flag

逆向入门

运行admin.exe???16位的应用程序

IDA打开感觉奇奇怪怪的,介素?

看起来类似010editer里面的格式,丢到wxmedit里面
一眼照片,这是逆向?服了

字符串丢到浏览器上 浏览器自动解码

扫码获取flag

OK现在逆向的前八题就做完了 再接再厉

END

建了一个微信的安全交流群,欢迎添加我微信备注进群,一起来聊天吹水哇,以及一个会发布安全相关内容的公众号,欢迎关注

加我拉你入群 黑糖安全公众号

BUGKU逆向reverse 1-8题的更多相关文章

  1. VK Cup 2016 - Round 1 (Div. 2 Edition) A. Bear and Reverse Radewoosh 水题

    A. Bear and Reverse Radewoosh 题目连接: http://www.codeforces.com/contest/658/problem/A Description Lima ...

  2. DDCTF2019逆向分析前俩题WriteUP

    DDCTF2019 笔者做了前俩道题.冷不丁过去一个月了.现在在此做一下WriteUp:题目链接: 1:题目1 2:题目2 reverse1:writeup: 1.程序打开后如下所示 2.查壳结果为U ...

  3. HDU 1062 Text Reverse(水题,字符串处理)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1062 解题报告:注意一行的末尾可能是空格,还有记得getchar()吃回车符. #include< ...

  4. codeforces 658A A. Bear and Reverse Radewoosh(水题)

    题目链接: A. Bear and Reverse Radewoosh time limit per test 2 seconds memory limit per test 256 megabyte ...

  5. HDU——1062Text Reverse(水题string::find系列+reverse)

    Text Reverse Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tot ...

  6. Bugku 逆向

    1.入门逆向 下载解压,在文件夹中打开命令行窗口执行一下:baby.exe 发现输出了一串字符,在将其放到IDA中然后是这样: 发现上面有一串输出和我们命令行窗口中的一样,但是下面为什么又多了一大溜东 ...

  7. bugku 逆向 take the maze

    看到如果判断正确之后 会生成一个png文件 直接用idc脚本生成: auto v,begin,end,dexbyte; v = fopen("flag.png", "wb ...

  8. bugku 逆向 love

    可以看到将输入先经过 sub_4110BE 这个函数进行加密 然后每一位加上下标本身 再和str2比较 正确就是right 点开加密函数: 关键语句就在这里 我们可以看到是算输入的字符按三个一组能分为 ...

  9. bugku的一道代码审计基础题:eval

    首先看到 include "flag.php",第一反应就应该是文件包含 直接先?hello=file:////etc, 然后啥也没 那就再检查一下代码,eval(var_dump ...

  10. 44个 Javascript 变态题解析 (上\下)

    第1题 ["1", "2", "3"].map(parseInt) 知识点: Array/map Number/parseInt JavaS ...

随机推荐

  1. Kubernetes 架构原则和对象设计

    Kubernet¶ Kubernetes 架构原则和对象设计¶ 什么是云计算¶ 云计算平台的分类¶ 以Openstack为典型的虚拟化平台 虚拟机构建和业务代码部署分离. 可变的基础架构使后续维护风险 ...

  2. 为什么 HashMap 会死循环?

    HashMap 死循环发生在 JDK 1.8 之前的版本中,它是指在并发环境下,因为多个线程同时进行 put 操作,导致链表形成环形数据结构,一旦形成环形数据结构,在 get(key) 的时候就会产生 ...

  3. 【重学C++】05 | 说透右值引用、移动语义、完美转发(下)

    文章首发 [重学C++]05 | 说透右值引用.移动语义.完美转发(下) 引言 大家好,我是只讲技术干货的会玩code,今天是[重学C++]的第五讲,在第四讲<[重学C++]04 | 说透右值引 ...

  4. 在asp.net core web api中添加efcore使用codefirst

    首先创建webapi项目,我这里使用的版本是.net6 在nuget中添加对应的工具包 红框标出来的是对应的数据库扩展包,mysql用mysql版,sqlserver用sqlserver版,选择正确的 ...

  5. ChatGPT 是否会夺走人们的工作

    ChatGPT 是否会夺走人们的工作? 最近,以 ChatGPT 为代表的人工智能项目在自然语言处理这一领域得到了一些突破性的进展,重新引发了人们对于"人工智能会抢走人类工作机会" ...

  6. 深入理解 Istio 流量管理的超时时间设置

    环境准备 部署 httpbin 服务: kubectl apply -f samples/httpbin/httpbin.yaml 部署 sleep 服务: kubectl apply -f samp ...

  7. 【后端面经-Java】Java创建线程的方法简介

    目录 1. 线程的基本概念 1.1 线程 1.2 线程状态和生命周期 2. 创建线程的四种方法 2.1 继承Thread类 2.2 实现Runnable接口 2.3 实现Callable接口 2.4 ...

  8. 4.10 x64dbg 反汇编功能的封装

    LyScript 插件提供的反汇编系列函数虽然能够实现基本的反汇编功能,但在实际使用中,可能会遇到一些更为复杂的需求,此时就需要根据自身需要进行二次开发,以实现更加高级的功能.本章将继续深入探索反汇编 ...

  9. Open LLM 排行榜近况

    Open LLM 排行榜是 Hugging Face 设立的一个用于评测开放大语言模型的公开榜单.最近,随着 Falcon 的发布并在 Open LLM 排行榜 上疯狂屠榜,围绕这个榜单在推特上掀起了 ...

  10. java端口被占用解决办法