wustctf2020_babyfmt
信息收集
checksec
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
常规的保护基本都开了;
执行程序
$ ./wustctf2020_babyfmt dididada..... tell me the time:13 23 11 ok! time is 13:23:11 1. leak 2. fmt_attack 3. get_flag 4. exit >>
|
IDA
放到ida64中分析;
main()
int __cdecl __noreturn main(int argc, const char **argv, const char **envp) { int v3; int v4; unsigned int choice; unsigned __int64 v6;
v6 = __readfsqword(0x28u); initial(); ask_time(argc, argv); v3 = 0; v4 = 0; while ( 1 ) { while ( 1 ) { while ( 1 ) { menu(); choice = get_int(); if ( choice != 2 ) break; fmt_attack(&v3); } if ( choice > 2 ) break; if ( choice == 1 ) leak(&v4); } if ( choice == 3 ) get_flag(); if ( choice == 4 ) { puts("Bye!"); exit(0); } } }
|
可以看到初始化函数initial()
、获取并输出时间的函数ask_time()
;
initial()
unsigned __int64 initial() { int fd; unsigned __int64 v2;
v2 = __readfsqword(0x28u); setvbuf(stdin, 0LL, 2, 0LL); setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stderr, 0LL, 2, 0LL); fd = open("/dev/urandom", 0); if ( read(fd, secret, 0x40uLL) < 0 ) { puts("read error!"); exit(1); } close(fd); return __readfsqword(0x28u) ^ v2; }
|
向.bss
段上的secret
写入随机数;
ask_time()
unsigned __int64 ask_time() { __int64 v1; __int64 v2; __int64 v3; unsigned __int64 v4;
v4 = __readfsqword(0x28u); puts("dididada....."); printf("tell me the time:"); _isoc99_scanf("%ld", &v1); _isoc99_scanf("%ld", &v2); _isoc99_scanf("%ld", &v3); printf("ok! time is %ld:%ld:%ld\n", v1, v2, v3); return __readfsqword(0x28u) ^ v4; }
|
获取了三个用户输入的三个参数,并且输出;
接下来看关键的格式化漏洞函数fmt_attack()
;
fmt_attack()
unsigned __int64 __fastcall fmt_attack(int *a1) { char format[56]; unsigned __int64 v3;
v3 = __readfsqword(0x28u); memset(format, 0, 0x30uLL); if ( *a1 > 0 ) { puts("No way!"); exit(1); } *a1 = 1; read_n(format, 40LL, format); printf(format); return __readfsqword(0x28u) ^ v3; }
|