攻防世界逆向高手题之catch-me

99 篇文章 36 订阅

攻防世界逆向高手题之catch-me

继续开启全栈梦想之逆向之旅~
这题是攻防世界逆向高手题的catch-me
在这里插入图片描述
.
.
照例下载附件,结果两次都提示是用7z打开(解压),所以要解压两次才能得到真正文件:
在这里插入图片描述
.
.
最后得到的文件是一个64位的ELF文件:
在这里插入图片描述
.
.
照例运行一下程序查看主要回显信息:
在这里插入图片描述
.
.
(这里积累第一个经验)
啥也没输入就直接程序结束了,回顾一下前面做的不用输入的类型,那时检查文件中flag的,而且没有对应文件就闪退的。
在这里插入图片描述
.
.
那么这题也是不用输入的,这种不用输入的程序都是直接利用程序外部的一些东西来作为条件继续执行的,所以我们这次也是要修改程序外的一些东西,来符合程序的执行。
.
.
照例扔入64IDA中查看main函数逻辑:

(这里积累第二个经验)
积累一些函数的利用:
int _mm_cvtsi128_si32 (__m128i a);
返回值:r := a0
.
_mm_add_epi32(a, b);
返回值:a+b
.
__m128i _mm_slli_si128 (__m128i a, int imm);
4字节128位移位操作
返回值:r := a << (imm * 8)
.
__m128i _mm_unpackhi_epi16 (__m128i a, __m128i b);
将 a 中的高 4 个有符号或无符号 16 位整数与 b 中的高 4 个有符号或无符号 16 位整数交错。a在前,b在后。
返回值:
r0 := a4 ; r1 := b4
r2 := a5 ; r3 := b5
r4 := a6 ; r5 := b6
r6 := a7 ; r7 := b7
.
__m128i _mm_unpacklo_epi16 (__m128i a, __m128i b);
将 a 中的低 4 个有符号或无符号 16 位整数与 b 中的低 4 个有符号或无符号 16 位整数交错。a在前,b在后。
返回值:
r0 := a0 ; r1 := b0
r2 := a1 ; r3 := b1
r4 := a2 ; r5 := b2
r6 := a3 ; r7 := b3
.
__m128i _mm_unpacklo_epi8 (__m128i a, __m128i b);
将 a 中的低 8 个有符号或无符号 8 位整数与 b 中的低 8 个有符号或无符号 8 位整数交错。a在前,b在后。
返回值:
r0 := a0 ; r1 := b0
r2 := a1 ; r3 := b1

r14 := a7 ; r15 := b7
.
__m128i _mm_unpackhi_epi8 (__m128i a, __m128i b);
将 a 中的高 8 个有符号或无符号 8 位整数与 b 中的高 8 个有符号或无符号 8 位整数交错。a在前,b在后。
返回值:
r0 := a8 ; r1 := b8
r2 := a9 ; r3 := b9

r14 := a15 ; r15 := b15
.
__m128i _mm_load_si128 (__m128i *p);
加载 128 位值。
返回值:
返回加载到代表寄存器的变量中的值,地址 p 必须是 16 字节对齐的。
.
char *getenv(const char *name)函数:(get environment)
搜索 name 所指向的环境字符串,并返回相关的值。

在这里插入图片描述
.
.
.
(这里积累第三个经验)
所以在前面v3是直接生成的,这里能获取程序外部的只有getenv函数,那么关键地方就是这里if ( getenv("ASIS") && (*(_DWORD *)getenv("CTF") ^ v3) == 0xFEEBFEEB )

v3动态调试发现值是0xB11924E1,那么我们要设置满足条件的ASISCTF环境变量才能执行if语句,才有可能获取flag

这里其实很多其它博客都忽略了一点就是getenv("ASIS")应该是要爆破出来的,首先附上C语言运算符的优先级,从图中可以看出只要前面(*(_DWORD *)getenv("CTF") ^ v3) == 0xFEEBFEEB满足,那么后面getenv("ASIS")只要不是0就可以。

(注意这里&&不要和&位运算搞混了,&&是逻辑与,&是位与。)
在这里插入图片描述
.
.
getenv(“CTF”)=0xFEEBFEEB^v3,可以算出等于0x4ff2da0a,那么getenv("ASIS")是多少呢?只能猜测它和getenv("CTF")一样都是0x4ff2da0a试一试了。
.
.
(这里积累第四个经验)
所以我们导入linux的环境变量,这里也补充一些基本知识:(注意:export只能在当前终端中有效,终端关闭就没用了)

(通过printf可以导入十六进制整数类型,值得积累)
export ASIS="$(printf "\x0a\xda\xf2\x4f")"				#注意参数是从低位到高位的
export CTF="$(printf "\x0a\xda\xf2\x4f")"

在这里插入图片描述
.
.
然后直接运行,果不其然getenv("ASIS")等于getenv("CTF"),得出真实的flag了:
在这里插入图片描述
.
.
.
.
(这里积累第5个经验)
另一种方法就是我们既然知道了getenv("ASIS")的值,我们也可以直接自己生成flag啊。

首先第一个要注意的是v30xB11924E1本来应该是小端顺序逆序存储在内存中的,可是这里红框中HIBYTE、BYTE2、BYTE1、BYTE直接把v3按大端顺序存储了,这点要特别注意,而且还经过了位与&处理。

然后就是黄框中在v3数组后拼接小端getenv("ASIS"),最后我们直接用Export data直接导出haystack原始的32位值进行处理即可。
在这里插入图片描述
.
.
.
附上脚本,注意源代码中是[i & 7]差点看错成[i % 7]了:

key1=0xFEEBFEEB		
key2=0xB11924E1
key3=key1^key2		#0x4ff2da0a
print(hex(key3&(key3^key2)))
list1=[0xb1,0x19&0xfd,0x24&0xdf,0xe1&0xbf,0x0a,0xda,0xf2,0x4f]#v3按大端顺序被截取了
flag=[  0x87, 0x29, 0x34, 0xC5, 0x55, 0xB0, 0xC2, 0x2D, 0xEE, 0x60, 0x34, 0xD4, 0x55, 0xEE, 0x80, 0x7C,0xEE, 0x2F, 0x37, 0x96, 0x3D, 0xEB,0x9C, 0x79, 0xEE, 0x2C, 0x33, 0x95, 0x78, 0xED, 0xC1, 0x2B]
for i in range(32):
	flag[i]^=list1[i&7]
print('ASIS{'+''.join(map(chr,flag))+'}')

.
.
结果:
在这里插入图片描述
.
.
.
总结:

1:
(这里积累第一个经验)
啥也没输入就直接程序结束了,回顾一下前面做的不用输入的类型,那时检查文件中flag的,而且没有对应文件就闪退的。
在这里插入图片描述
.
那么这题也是不用输入的,这种不用输入的程序都是直接利用程序外部的一些东西来作为条件继续执行的,所以我们这次也是要修改程序外的一些东西,来符合程序的执行。

2:
(这里积累第二个经验)
积累一些函数的利用:
int _mm_cvtsi128_si32 (__m128i a);
返回值:r := a0
.
_mm_add_epi32(a, b);
返回值:a+b
.
__m128i _mm_slli_si128 (__m128i a, int imm);
4字节128位移位操作
返回值:r := a << (imm * 8)
.
__m128i _mm_unpackhi_epi16 (__m128i a, __m128i b);
将 a 中的高 4 个有符号或无符号 16 位整数与 b 中的高 4 个有符号或无符号 16 位整数交错。a在前,b在后。
返回值:
r0 := a4 ; r1 := b4
r2 := a5 ; r3 := b5
r4 := a6 ; r5 := b6
r6 := a7 ; r7 := b7
.
__m128i _mm_unpacklo_epi16 (__m128i a, __m128i b);
将 a 中的低 4 个有符号或无符号 16 位整数与 b 中的低 4 个有符号或无符号 16 位整数交错。a在前,b在后。
返回值:
r0 := a0 ; r1 := b0
r2 := a1 ; r3 := b1
r4 := a2 ; r5 := b2
r6 := a3 ; r7 := b3
.
__m128i _mm_unpacklo_epi8 (__m128i a, __m128i b);
将 a 中的低 8 个有符号或无符号 8 位整数与 b 中的低 8 个有符号或无符号 8 位整数交错。a在前,b在后。
返回值:
r0 := a0 ; r1 := b0
r2 := a1 ; r3 := b1

r14 := a7 ; r15 := b7
.
__m128i _mm_unpackhi_epi8 (__m128i a, __m128i b);
将 a 中的高 8 个有符号或无符号 8 位整数与 b 中的高 8 个有符号或无符号 8 位整数交错。a在前,b在后。
返回值:
r0 := a8 ; r1 := b8
r2 := a9 ; r3 := b9

r14 := a15 ; r15 := b15
.
__m128i _mm_load_si128 (__m128i *p);
加载 128 位值。
返回值:
返回加载到代表寄存器的变量中的值,地址 p 必须是 16 字节对齐的。
.
char *getenv(const char *name)函数:(get environment)
搜索 name 所指向的环境字符串,并返回相关的值。

3:
(这里积累第三个经验)
所以在前面v3是直接生成的,这里能获取程序外部的只有getenv函数,那么关键地方就是这里if ( getenv("ASIS") && (*(_DWORD *)getenv("CTF") ^ v3) == 0xFEEBFEEB )
.
v3动态调试发现值是0xB11924E1,那么我们要设置满足条件的ASISCTF环境变量才能执行if语句,才有可能获取flag
.
这里其实很多其它博客都忽略了一点就是getenv("ASIS")应该是要爆破出来的,首先附上C语言运算符的优先级,从图中可以看出只要前面(*(_DWORD *)getenv("CTF") ^ v3) == 0xFEEBFEEB满足,那么后面getenv("ASIS")只要不是0就可以。
.
(注意这里&&不要和&位运算搞混了,&&是逻辑与,&是位与。)
.在这里插入图片描述

4:
(这里积累第四个经验)
所以我们导入linux的环境变量,这里也补充一些基本知识:(注意:export只能在当前终端中有效,终端关闭就没用了)

在这里插入图片描述

(通过printf可以导入十六进制整数类型,值得积累)
export ASIS="$(printf "\x0a\xda\xf2\x4f")"				#注意参数是从低位到高位的
export CTF="$(printf "\x0a\xda\xf2\x4f")"

5:
(这里积累第5个经验)
另一种方法就是我们既然知道了getenv("ASIS")的值,我们也可以直接自己生成flag啊。
.
首先第一个要注意的是v30xB11924E1本来应该是小端顺序逆序存储在内存中的,可是这里红框中HIBYTE、BYTE2、BYTE1、BYTE直接把v3按大端顺序存储了,这点要特别注意,而且还经过了位与&处理。
.
然后就是黄框中在v3数组后拼接小端getenv("ASIS"),最后我们直接用Export data直接导出haystack原始的32位值进行处理即可。

解毕!敬礼!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐一 · 林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值