0%

[GXYCTF 2019]luck_guy

2025-12-30 05:58By
shawnctf
动态调试C++patch

Problem: [GXYCTF 2019]luck_guy

思路

给了个 ELF,没开 PIE,反编译得到

unsigned __int64 get_flag() { unsigned int v0; // eax int i; // [rsp+4h] [rbp-3Ch] int j; // [rsp+8h] [rbp-38h] _QWORD s[5]; // [rsp+10h] [rbp-30h] BYREF unsigned __int64 v5; // [rsp+38h] [rbp-8h] v5 = __readfsqword(0x28u); v0 = time(0); 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: s = 0x7F666F6067756369LL; v5 = 0; 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; } int __fastcall patch_me(int a1) { if ( a1 % 2 == 1 ) return puts("just finished"); else return get_flag(); } int __fastcall main(int argc, const char **argv, const char **envp) { int v4; // [rsp+14h] [rbp-Ch] BYREF unsigned __int64 v5; // [rsp+18h] [rbp-8h] v5 = __readfsqword(0x28u); welcome(argc, argv, envp); puts("_________________"); puts("try to patch me and find flag"); v4 = 0; puts("please input a lucky number"); __isoc99_scanf("%d", &v4); patch_me(v4); puts("OK,see you again"); return 0; }

看来只要依次执行 get_flag 函数中的 case 4, case 5, case 1,就可以打印出 flag。那么就有三种做法。

  1. 静态分析,用脚本模拟 flag 的生成过程。
  2. 动态调试,在 rand 函数调用处打断点,break *0x400804,通过改变 rand 函数返回值 (p $rax=4),引导程序进入分支。
  3. patch ELF,然后运行。

EXP

s = [0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69] s.reverse() for i in range(len(s)): if i % 2 == 1: s[i] -= 2 else: s[i] -= 1 flag = 'GXY{do_not_' + ''.join([chr(c) for c in s]) print(flag)

总结

逆向,动态调试,patch。

还没有人赞赏,快来当第一个赞赏的人吧!
  
© 著作权归作者所有
加载失败
广告
×
评论区
添加新评论