【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy
2023-12-3 00:3:7 Author: 利刃信安攻防实验室(查看原文) 阅读量:9 收藏

BUUCTF 逆向题目 [GXYCTF2019]luck_guy

题目地址:

https://buuoj.cn/challenges#[GXYCTF2019]luck_guy

https://files.buuoj.cn/files/c4ae5d67227e2354c3b512d6bd8b180a/attachment.zip

首先,查壳

信息:     文件名: H:/第七届“强网杯”全国网络安全挑战赛/BUUCTF/[GXYCTF2019]luck_guy/luck_guy    大小: 9176(8.96 KiB)    操作系统: Ubuntu Linux(16.04.12,ABI: 2.6.32)    架构: AMD64    模式: 64 位    类型: EXEC    字节序: LE

使用IDA64打开文件

主程序main

关键函数patch_me

关键函数getflag

unsigned __int64 get_flag(){  unsigned int v0; // eax  int i; // [rsp+4h] [rbp-3Ch]  int j; // [rsp+8h] [rbp-38h]  __int64 s[5]; // [rsp+10h] [rbp-30h] BYREF  unsigned __int64 v5; // [rsp+38h] [rbp-8h]
v5 = __readfsqword(0x28u); v0 = time(0LL); srand(v0); for ( i = 0; i <= 4; ++i ) { switch ( rand() % 200 ) { case 1: puts("OK, it's flag:"); memset(s, 0, sizeof(s)); strcat((char *)s, f1); strcat((char *)s, &f2); printf("%s", (const char *)s); break; case 2: printf("Solar not like you"); break; case 3: printf("Solar want a girlfriend"); break; case 4: strcpy((char *)s, "icug`of\x7F"); strcat(&f2, (const char *)s); break; case 5: for ( j = 0; j <= 7; ++j ) { if ( j % 2 == 1 ) *(&f2 + j) -= 2; else --*(&f2 + j); } break; default: puts("emmm,you can't find flag 23333"); break; } } return __readfsqword(0x28u) ^ v5;}

flag为f1+f2,f1已知为GXY{do_not_,所以需要求f2 switch case需要的顺序为:case 4、case 5、case 1

s = 9180147350284624745LL; ,按H转为十六进制为0x7F666F6067756369LL;,使用时需要逆序

flag就是由f1和f2组成,f1已经告诉GXY{do_not,现在只需要求f2就行。

  • case4给f2赋值

  • case5,对f2进行处理

所以顺序是: case4>case5>case1

这里涉及数据在内存中存储的方式大小端问题。

涉及大小端存储问题,elf文件这种通常使用小端存储,而IDA会把内存中的数据自动转成大端存储,但是有些变量双击过去,在文本视图能直接看到转好的字符串,以f1为例

而有些却不能,这个时候就需要自己把字符串倒过来,比如我们在伪代码看到的 7F666F6067756369 ,可实际用这个字符串的时候应该用 69637567606F667F

规律:

IDA中赋值__int64是大端,双引号包裹字符串char是小端。

大端

小端

数据在内存中存储的方式:大端模式与小端模式

所谓的大端模式(Big-endian),是指数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;

所谓小端模式(Little-endian), 是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内在的低地址中,这种存储模式将地址的高低和数据位 权有效结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致;

假设一个十六进制数0x12345678

大端的存储方式是:12,34,56,78,然后读取的时候也是从前往后读

小端的存储方式是:78,56,34,12,然后读取的时候是从后往前读取

我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

继续分析代码

判断奇偶的程序,偶数就每个减1,奇数就每个都减2

编写代码

flag = 'GXY{do_not_'f2 = [0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69][::-1]
for i, value in enumerate(f2): flag += chr(value - (2 if i % 2 == 1 else 1))
print(flag)

flag{do_not_hate_me}

文章来源: http://mp.weixin.qq.com/s?__biz=MzU1Mjk3MDY1OA==&mid=2247508371&idx=3&sn=0922970b74c1d94dd3938761ba79329e&chksm=fbfb115ecc8c9848df78ce9659a468fdf3315003ddc61c0b50e50e031170f3b62429b7defa27&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh