ctfshow_内部赛
真的是签到
拿到是一个zip文件,并且没有后缀..手动给他加上.zip的后缀。
然后使用:ZipCenOp.jar 这个工具进行解密
1 | java -jar ZipCenOp.jar e xxx.zip 加密 |
然后就打开发现有一个“签到.exe”
然后用Die【我习惯了】这个工具看到这个是有一个ASPack(2.12-2.42)的壳
然后用Unpacker for ASPack 这个工具一键脱壳【我这里保存为222.exe】
用IDA打开后发现还有问题,一看还有一个UPX的壳【但是这里的upx没给版本】
我按照老样子去脱upx壳的时候不幸运的是错误了…【】
然后我换了一个脱壳机【在52破解里面找的】,就成功了…
然后用IDA打开
1 | flag = "" |
批量生产的伪劣产品
这个题,我用jadx 打开后,好多好多没啥思路【我对安卓的逆向还是不熟练】不能熟练的找到位置。
我也很蒙蔽,太多了结果搜索出来了…意料之外
来一个派森
拿到是一个exe文件
然后用die 看到是
然后看了这篇文章:https://cloud.tencent.com/developer/article/1872447
使用:pyinstxtractor.py 脚本提取pyc文件
1 | python pyinstxtractor.py check.exe |
得到一个exe_extracted的文件夹,然后再该文件夹中找到check.pyc文件然后再用在线的pyc反编译
我用的pyc 反编译的在线:https://www.toolkk.com/tools/pyc-decomplie
然后得到
1 | # uncompyle6 version 3.8.0 |
这里比较简单虽然我不算懂,但是看到了base58 和 ^
1 | check = [ 'A', '5', 'q', 'O', 'g', 'q', 'd', '\x7f', '[', '\x7f', 's', '{', 'G', 'A', 'x', '`', 'D', '@', 'K', |
好好学习天天向上
emm这个题我吐了
反正就是做不出来,最后看了Wp发现flag居然是猜到的
因为我们分析过后可以得知:flag是32个字符,然后是由于:abdefglostuyp{}_ 这几个字符组成的
flag{good_good_study_day_day_up}
屏幕裂开了
首先通过999 99定位位置【我凭着感觉看的】
点进去发现有一个checkflag,它有2个传参,感觉这个就是咱们要找的地方
然后看它在哪里被调用了,就在该目录的下面。
这里传了一个s还有一个啥东西【因为我没学过java我也不懂,菜鸡一个】
但是我这里找不到这个checkflag的函数在哪里….
不得不说Ai是真的好用….【大佬绕过】
知道这个native 是需要在本地库中完成的。本地库….但是我就一个apk文件,用jadx打开就是这样的,我咋才能找到这个呢?
后来我通过搜索了“native”这个关键字,但是大多都是介绍和实现这种方法的。也没告诉我这个玩意在哪里找..
百思不得其解的时候,我搜索了“CTF java native”这个关键字。成功的让我搜索到了一篇文章
:https://www.cnblogs.com/CimeLi/p/12285410.html
通过里面的方法我得到了“apk解压”这几个字。但是作为一个小白,我也不会。所以我去百度又搜索了一下apk如何解压。
得到了如下的答案:APK文件的后缀为. apk,但是其格式是压缩文件zip的格式。 可以通过WinZip、WinRAR等将其解压。 直接将该文件扩展名改为.zip就可以解压该文件来了解APK文件的结构。
然后我就把apk改成了zip,成功的解压了。
从上一篇文章中可得到so文件在lib下。但是这里又4个文件…
看到native下面有一个:System.loadLibrary(“native-lib”);
通过尝试最后确定为:\armeabi-v7a文件夹下的libnative-lib.so文件
我们用IDA将它打开,进去也是一脸蒙蔽,但是通过左边的函数窗口搜索“checkflag”
然后就得到了:
下面那个for循环还是比较容易看懂的,现在的问题就是不知道v9是什么,然后StringUTFChars是什么。
但是通过strlen(StringUTFChars) == 63这个,我猜测是flag的长度,flag也是我们输入的东西。回到jadx里面。在调用checkflag的时候传入了2个参数
1 | mainActivity.checkflag(mainActivity.s, MainActivity.this.input.getText().toString()) |
后面:MainActivity.this.input.getText().toString() 这一个长串的感觉是我们输入的flag,前面的
mainActivity.s是char[] s = new char[256];但是上面的代码对s进行了处理。我们现在就来分析一下这个s是什么。
1 | String key = "InfinityLoop"; |
看到:MainActivity.this.hit_count >= 99999就知道首先要循环这么多次
j = (char) (((MainActivity.this.s[i3] + j) + MainActivity.this.k[i3]) % 256);
//上面这一行是将s[]里面的数据打乱。
char tmp = MainActivity.this.s[i3];
MainActivity.this.s[i3] = MainActivity.this.s[j];
MainActivity.this.s[j] = tmp;//上面3行是一个交换
这里就是将s中的数据打乱的代码
这里来详细分析一下s和k吧:
这段代码中,s
和 k
是两个字符数组,分别用于存储操作数据和密钥。它们被用于一个点击计数器应用的加密操作。以下是它们的具体操作:
s
数组初始化:
在onCreate
方法中,s
数组被初始化为包含 256 个字符的数组,每个字符都是一个从 0 到 255 的连续整数。这表示s
数组最初包含了所有可能的字节值。k
数组初始化:
同样在onCreate
方法中,k
数组被初始化为一个与字符串key
相关的字符数组。这个字符串似乎是 “InfinityLoop”。初始化过程将密钥字符串的字符循环放置到k
数组中,如果key
字符串的长度小于 256,则会重复使用字符串的字符。onClick
方法中的操作:
在按钮点击事件处理程序中,onClick
方法执行以下操作:hit_count
被递增,记录点击次数。- 通过一个循环迭代处理
s
数组中的每个元素,以及k
数组中的相应元素。 - 在每次循环迭代中,
j
的值被计算为((s[i3] + j) + k[i3]) % 256
,其中%
表示取模操作。 - 然后,
s
数组中的第i3
个元素与s
数组中的第j
个元素交换位置。
这个操作看起来是一种类似于加密的操作,根据点击次数以及预先初始化的
s
数组和k
数组进行数据交换。每次点击后,s
数组的状态会发生改变,从而导致数据的混淆和加密效果。当点击次数达到 99999 时,按钮btn2
会被启用,这似乎是一个触发条件。
总之,s
和 k
数组在 onClick
方法中被用于执行一种加密操作,其中 s
用于存储数据,k
用于存储密钥,每次点击都会导致 s
数组的变换。
用python实现一下:
1 | s = [i for i in range(256)] |
然后就得到了这个s
后面就是将s和flag传进去.so文件,然后和里面的answer进行比较,这个后面的还是比较好理解的了。中间有一个不太好理解的v9[i] = *(_BYTE *)(CharArrayElements + 2 * i);
但是上面的文章说没用…那就没用吧
其实我不放心还问了Ai:
OKOK,后面就不需要分析了吧
最后的代码:
1 | s = [i for i in range(256)] |
v6 = (v6 + v9[v7]) & 0xff
如果不进行 & 操作就会报错:超出范围
因为IDA分析出来是:v6 = (unsigned __int8)(v6 + v9[v7]);
&0xff的作用是截断
- 而跟& 0xff运算的意义其实就是截断,将123456的高位右移8位,通过0xff截取出来。 实际意义就是取字节,比如一个4字节的数,需要将每个字节内容取出来转换出目标数据,那么通过>> 并且&0xff 运算就可以去除想要的部分。
v9[(v9[v7] +v9[v6])%256]
如果不进行%256也会报错:超出范围
同理:(unsigned __int8)(v9[v7] + v9[v6])
所以需要:%256