【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

admin 2023年12月4日02:01:29评论25 views字数 2123阅读7分4秒阅读模式

BUUCTF 逆向题目 [GXYCTF2019]luck_guy

题目地址:

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

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

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

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

首先,查壳

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

信息:     文件名: 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

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

关键函数patch_me

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

关键函数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`ofx7F"); 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;,使用时需要逆序

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

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

  • case4给f2赋值

  • case5,对f2进行处理

所以顺序是: case4>case5>case1

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

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

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

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

规律:

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

大端

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

小端

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

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

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

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

假设一个十六进制数0x12345678

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

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

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

继续分析代码

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

判断奇偶的程序,偶数就每个减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)

【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

flag{do_not_hate_me}

原文始发于微信公众号(利刃信安攻防实验室):【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guy

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月4日02:01:29
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【逆向分析】BUUCTF 逆向题目 [GXYCTF2019]luck_guyhttps://cn-sec.com/archives/2263722.html

发表评论

匿名网友 填写信息