1.攻防世界--新手区--open-source
下载拿到c语言文件,都不用反汇编,直接观察代码。让他们都if判断失败不就可以最终执行输出key的代码了
#include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { //argc ==4 if (argc != 4) { printf("what?\n"); exit(1); } //first ==0xcafe unsigned int first = atoi(argv[1]); if (first != 0xcafe) { printf("you are wrong, sorry.\n"); exit(2); } //这个地方其实我不确定不同的答案能否拿到相同的结果,所以我用python跑了一下 unsigned int second = atoi(argv[2]); if (second % 5 == 3 || second % 17 != 8) { printf("ha, you won't get it!\n"); exit(3); } //这个地方让argv[3] == h4cky0u if (strcmp("h4cky0u", argv[3])) { printf("so close, dude!\n"); exit(4); } printf("Brr wrrr grr\n"); //我在这里加了一个printf("%d %d",first,strlen(argv[3])); unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207; printf("Get your key: "); printf("%x\n", hash); return 0; }
用python代码及输出结果
for i in range(1000): if i%5!=3 and i%17==8: print(hex(51966 * 31337 + (i % 17) * 11 + 7 - 1615810207))
发现输出结果相同,成功提交。
题后思考
该题目中出现的问题以及自己的一些见解:
1. argc == 4不能成功通过第一个if,这个没找到原因(当然第一个判断也没啥用) 2.argc是命令行总的参数个数,也就是说一共有4个参数;argv[]存放的是main函数的参数,argv[]是字符串数组(我当时以为是指针数组,存放的是指针,现在想想感觉也没问题,毕竟指针指向的也是字符串不是)第0个参数是程序的全名,依次是用户通过命令行输入的参数。 3. strcmp()这个函数相同返回0,不同返回1!!!
2.攻防世界--新手区--python-trade
pyc文件直接反汇编,生成.pyc_dis,notepad++打开
# Embedded file name: 1.py import base64 def encode(message): s = '' for i in message: x = ord(i) ^ 32 x = x + 16 s += chr(x) return base64.b64encode(s) correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt' flag = '' print 'Input flag:' flag = raw_input() if encode(flag) == correct: print 'correct' else: print 'wrong'
由以上可以看出来逻辑是:对flag加密,加密之后==correct,加密方法就是encode。逆向逻辑:对encode进行逆向。
代码如下:
import base64 def decode(message): s = base64.b64decode(message) st = '' for i in s: #print(type(i))可以使用这种方式测试i的类型 tmp = i - 16 #tmp = ord(i)-16 # 这里运行会出错的原因是ord()函数接受的类型是一个长度为1的字符串, # 而在python3当中传入的i已经是一个整型数了(b64decode()函数返回值就是16进制数), #所以直接i-16就可以。网上的其他blog中提到py2不会出现这种问题,做了测试, # py2上述语法确实不会出问题,但是会报新的错误 tmp = tmp^32 st += chr(tmp) return st correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt' str = decode(correct) print(str)
题后思考
见代码注释
3.攻防世界--新手区--re1
拿到一个exe文件,查壳,发现32位无壳exe,ida打开,直接找到main函数
int __cdecl main(int argc, const char **argv, const char **envp) { int v3; // eax __int128 v5; // [esp+0h] [ebp-44h] __int64 v6; // [esp+10h] [ebp-34h] int v7; // [esp+18h] [ebp-2Ch] __int16 v8; // [esp+1Ch] [ebp-28h] char v9; // [esp+20h] [ebp-24h] _mm_storeu_si128((__m128i *)&v5, _mm_loadu_si128((const __m128i *)&xmmword_413E34)); v7 = 0; v6 = qword_413E44; v8 = 0; printf("欢迎来到DUTCTF呦\n"); printf("这是一道很可爱很简单的逆向题呦\n"); printf("输入flag吧:"); scanf("%s", &v9); v3 = strcmp((const char *)&v5, &v9); if ( v3 ) v3 = -(v3 < 0) | 1; if ( v3 ) printf(aFlag_0); else printf((const char *)&dword_413E90); system("pause"); return 0; }
根据反汇编看逻辑:v9也就是flag,v9和v5做比较,不同为1,执行if语句,使出aFlag_0(见下图)相同为0,直接执行else语句,输出dword_413E90(见下图)
逻辑分析清楚之后,就找到v5即可,对v5有操作的函数只有 _mm_storeu_si128()函数,经查询发现,这是常用指令
指令名:void _mm_store_si128 ( __m128i *p, __m128i a); 功能:可存储128位数据; 说明:将__m128i 变量a的值存储到p所指定的变量中去; 注意:p必须是一个16-bit对齐的一个变量的地址。
查看xmmword_413E34,
因为是小端存储,将字符串逆置一下就可以。
我当时做的时候,发现下面有qword_413E44,因为是小端存储,逆置将他们连接,成功提交。
其他解题方法
-
判断出xmmword之后,直接去16进制中搜索DUTCTF,可以拿到flag
-
动态调试
这个地方手贱非得ida动调(主要是喜欢ida那种有反汇编的调试),失败了(失败原因是ida需要使用7.5版本的ida pro),在寄存器窗口的ECX中可以看到,跳转地址直接去,转成字符串,直接有flag。
od动调(虚拟机的od也失败了,本机装了个od,成功打开,然后因为自己动调太菜了,没调出来,哭哭了)
3. 打开文件的时候直接二进制文件打开,直接搜就有flag
题后思考
-
反汇编代码存在一定问题,并未对v6进行操作就v5就自动连接了(未解决)
-
_mm_storeu_si128()函数
-
字符串逆置方式()
-
动调能力太差
4.攻防世界--新手区--game
idapro打开,f5反汇编查看逻辑
我的断点直接下在了if判断上,然后修改寄存器的值,保证每个cmp都能够执行
由上图可以看出,虽然没有全部显现亮灯,但是显示了flag
其他解题方法
后来看人家的wp,我更无语了。
方法1:这个game竟然是输入12345678,自己就出flag(现在想想也合理,因为他是先判断1,在判断2,依次判断的,我只能说还是自己太菜了,get到了)
方法2:静态反汇编 发现自己的ida跟博主的ida显示不同,所以我换了个版本的ida打开
这个就比较明显,v2-v58是前面的,剩下的是后面的,写个脚本即可
a = [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] b = [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] for i in range(len(a)) : b[i] = b[i] ^a[i] b[i] = b[i] ^0x13 print(chr(b[i]),end="")
题后思考
这个题静态反汇编逻辑出现问题,因为我找到的核心函数是sub_6fa7be,但是这个函数最下面的比较应该是可以出flag的,我找出来的v3长度只有22,没法进行异或,所以改变了方式,使用了动态调试的方法。
buu做过,但是当时是静态逆出来的,无语了
5.攻防世界--新手区--Hello, CTF
ida打开,main函数,拿到一串字符串
静态逻辑分析,发现,v10跟v13相同就输出success,此时我并不清楚v9跟v13哪个是flag,v9根据逻辑可以看出来是17位长度,然后把v9中的数据存放到buffer中(此处sprintf函数功能是猜测的,因为这里并没有输出操作),然后把buffer追加到v10后面就可以了。可以发现v13是16进制数,输出一下字符串,得到flag
s=bytes.fromhex("437261636b4d654a757374466f7246756e") print(s)
动态调试尝试过,但是因为这题就是单纯的对比,调试成功也是显示success,没有很大的用处。