# Java-Script-Kiddie

Point: 400

## Category

Web Exploitation

## Question

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

## Hint

This is only a JavaScript problem.

## Solution

Upon accessing the site, we find a textbox with a submit button next to it. When we press submit, a placeholder image icon appears. We suspect that inputting a correct password into the box will make the image valid. Let's inspect the javascript, given that this is a JS-only problem by the hint:

Looking on source code, we'll see assemble\_png function.

```bash
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.ap(null, new Uint8Array(result)));
    return false;
}
```

We note the AJAX query for bytes. Accessing <https://2019shell1.picoctf.com/problem/37826/bytes> gives us a large array of bytes represented as integers. We also read the code to see that bytes is treated as a 2D array with 16 columns; each column is shifted by the corresponding value in key. (For instance, if the third digit in key is 7, then the third column is shifted down by 7). We can write a python script to help visualize this:

```bash
def tohex(a):
    return "{:02x}".format(a)

f = open("bytes.txt", "r")
bytelist = map(int, f.read().split(" "))
f.close()

key = "0000000000000000"
result = [0 for x in bytelist]
SIZE = 16
for i in range(SIZE):
    shift = ord(key[i]) - 48
    for j in range(len(result) / SIZE):
        result[(j*SIZE + i)] = bytelist[(((j+shift)*SIZE) % len(bytelist)) + i]

for i in range(len(result) / SIZE):
    print ' '.join(map(tohex, result[i*SIZE:(i+1)*SIZE]))
```

As output, we get:

```bash
35 48 9b 0e 0c 0a b7 0a f8 17 fd 0c fc 00 00 4e
1b 9f e1 74 82 00 72 72 e6 c0 c5 81 7f 48 44 00
17 4a ef cc 0d 49 00 41 f1 1d 00 21 17 c0 5f 52
44 97 93 1b 00 24 1a 1b f6 fe 00 54 00 4d 6e 6c
89 13 6f 60 4c 44 01 e5 00 23 00 8b 00 06 39 9c
00 4b fa 47 05 bd 44 20 00 31 00 00 49 43 e3 52
a4 8f 99 72 03 14 2f 88 01 e2 9c 00 00 ea 17 c8
40 6b 3c 02 1d ab 82 8e 54 00 c8 0d 9b f1 e2 30
ae ae 42 5f f8 5b 5a e4 c9 00 97 00 e0 cc ac df
c2 50 4e 99 33 7f 0e 3f 48 00 45 ed 75 bd 40 7b
e2 00 01 31 e6 00 fd 31 18 00 5e 51 6f a1 ec b2
e3 00 00 fc 9e be 92 1f 17 78 99 45 78 8c 37 a7
a2 10 85 0d cf b4 b4 e2 75 07 e5 49 cc a0 1d 6b
47 06 47 4f ce 04 64 1f 08 a0 e6 bc e2 08 60 01
1a 96 99 e4 7f 09 d9 aa e2 be ff 1f 18 e6 bf 02
00 33 36 cc 54 c4 3f 13 7d 2f f2 dd 7f b0 78 f8
f6 2d 5a 9c e5 c5 c2 98 f1 93 a7 a7 67 87 a6 fb
80 3f e2 90 9f 97 79 98 bf a0 af c5 1b e4 58 02
0f 45 92 06 ff 88 ff 24 bf 4f 6f 24 ae 7f f1 91
fc 18 cc 99 8e 1d 1f 82 61 5d 53 c4 04 c0 d2 07
f7 eb c2 c4 a8 1a 7d f4 a1 e7 b1 40 09 c7 af b7
1c 58 ec 3d a2 37 96 dd 0f c6 d5 2f 02 78 d9 ff
c6 e9 95 61 fc 55 e1 d5 e3 9b b4 f9 cd 23 1d 52
44 f1 83 82 f5 bb bf bd 5a bf b1 e0 18 92 f0 a4
0b 5c 7f f2 0d 4c 56 37 ba 43 07 5f a2 c5 e5 aa
fa d1 7b 61 85 f1 52 b6 84 3f 7c aa 88 59 ef 4e
6f 2b 02 e7 b7 ec a1 35 a4 08 79 c9 39 41 b7 31
bf 68 ab d2 7f d3 7e bb 7b ef 57 ec b7 82 77 72
33 1e d9 d6 79 ab 07 b5 d5 c8 7a 35 e9 d2 b7 26
bd a4 6f f9 19 c4 62 28 1f 9c cf 6d 95 5b 22 44
0c 16 ca cd 5b e0 e8 67 c9 34 8e dd 33 7c 9e 9f
7d 79 7c 42 34 27 14 e7 3e a9 b0 57 1f 9f 91 7c
3e e5 f2 33 af c1 f9 45 eb 80 a7 02 be be 7a 2d
d5 f1 a2 6e ed 9a 5b f3 31 05 ea 07 e9 ac 0c be
99 5e 5e 13 f5 23 4b 64 5a e8 2e 8e 99 96 1c bc
39 e5 e7 ea bc 2e ff 7f e9 04 1e 33 ef 49 57 17
d5 0b e3 4a f9 ee f2 e7 bd aa ff 6f af 86 00 da
e9 89 37 ca 7f 90 fe 64 fd 5d 5b 9f a5 f6 fe 00
db 5f 60 e1 bf 7d 94 78 ff a0 01 d3 02 c4 9f a4
17 92 74 37 21 b4 c6 95 be 5b 24 9e 3f 7f 02 c4
53 76 eb de f4 00 c0 00 fb 4d fe 97 8a 49 45 ff
```

If instead the key were to be `0070000000000000`, the third column would begin with `3c, 42, 4e, 01,` etc.

From here, the key observation to make is that this data must represent a PNG image; we also know that a PNG must begin with the following header:

```bash
89 50 4e 47 0d 0a 1a 0a
```

Based on this alone, we can find that the first half of the key is 49952030, which rotates the columns to get the header to be correct. Furthermore, we know that this header must be immediately followed by an IHDR chunk, which always has length 0d. Thus, our first row must look like:

```bash
89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52
```

We can thus quickly find that the correct key must be of the form `49952030???75112`. The three ?s are there because the corresponding byte (`00`) has multiple possible values (`4,5,6` for the first, `7,8,9` for the second (we can't have the two-digit `10`), and `2,3,4,5` for the third). We could brute force these possibilites, but we can reduce our search space by look at the second row. By the spec, this corresponds to the content of the IHDR chunk, which must look like:

| First column        | Second column |
| ------------------- | ------------- |
| Width:              | 4 bytes       |
| Height:             | 4 bytes       |
| Bit depth:          | 1 byte        |
| Color type:         | 1 byte        |
| Compression method: | 1 byte        |
| Filter method:      | 1 byte        |
| Interlace method:   | 1 byte        |

Let's see what the three `?`s must be:

* The first ? must make the bit depth valid (`1, 2, 4, 8, 16`); the only way we can do this is having `*` the first `? = 5`.
* The second `?` must make the color type valid (0, 3 based on the `bit depth`); we must have the second `? = 7,8,9`.
* The third `?` must make the `compression method` valid (0 is the only one allowed); we must have the third `? = 2,3,4`.

With only nine possibilites left, we can simply brute force the possible keys:

```bash
4995203057275112, 4995203057375112, 4995203057475112, 4995203058275112, 4995203058375112, 4995203058475112, 4995203059275112, 4995203059375112, 4995203059475112.
```

The last one gives us a QR code:

![QR CODE](https://github.com/m14ghost/PicoCTF-2019-Writeup/blob/master/Web%20Exploitation/qr.png)

## Flag

picoCTF{b7794daf95ade3c353aa8618c3a7e2c6}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://thomasbui.gitbook.io/blog/software-security/ctfs-write-ups/writeups-picoctf-collection/https-github.com-m14ghost-picoctf-2019-writeup/web-exploitation-1/java-script-kiddie.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
