Rating: 5.0

> Broken Packer
>
> rev150
>
> Description: Looks like this packer can not unpack what has been packed :( There are 2 mistakes in unpacking procedure. It leads to the error. Try to fix unpacker and figure out what is inside.
>
> Webpage: [broken_packer.zip](https://0xd13a.github.io/ctfs/hackit2017/rev150/broken_packer.zip)

We are given an archive with 2 files - a packer and a packed executable. As it later turns out the packer is not even needed to solve it, so let's concentrate on the packed application, ```packed```.

Running the application from command line yields a segfault:

```sh
$ ./packed
Segmentation fault
```

We better fix those errors the description is talking about. Let's open it in IDA:

![img1.png](https://0xd13a.github.io/ctfs/hackit2017/rev150/img1.png)

The unpacking routine is very simple and the errors are easy to spot. The loop index is in ```rax``` so ```xor [rdx], dl``` should really be ```xor [rax], dl```. Also, we go byte-by-byte, so the index increment should be ```add rax, 1```, not ```add rax,2```. Let's patch the binary to correct these.

Patching the application gets us further:

```sh
$ ./packed
The hardest part is overcome.
Segmentation fault
```

Let's debug the application and look at the disassembly to see what function outputs that:

```
.text:0000000000400BA9 sub_400BA9 proc near ; DATA XREF: sub_400990+1D
.text:0000000000400BA9
.text:0000000000400BA9 var_10 = qword ptr -10h
.text:0000000000400BA9 var_4 = dword ptr -4
.text:0000000000400BA9
.text:0000000000400BA9 push rbp
.text:0000000000400BAA mov rbp, rsp
.text:0000000000400BAD sub rsp, 10h
.text:0000000000400BB1 mov [rbp+var_4], edi
.text:0000000000400BB4 mov [rbp+var_10], rsi
.text:0000000000400BB8 lea rdi, aTheHardestPart ; "The hardest part is overcome."
.text:0000000000400BBF call sub_407FC0
.text:0000000000400BC4 mov rax, [rbp+var_10]
.text:0000000000400BC8 add rax, 8
.text:0000000000400BCC mov rax, [rax]
.text:0000000000400BCF lea rsi, aCryp ; "cryp"
.text:0000000000400BD6 mov rdi, rax
.text:0000000000400BD9 call sub_400370
.text:0000000000400BDE test eax, eax
.text:0000000000400BE0 jnz short loc_400BF5
.text:0000000000400BE2 mov rax, [rbp+var_10]
.text:0000000000400BE6 add rax, 10h
.text:0000000000400BEA mov rax, [rax]
.text:0000000000400BED mov rdi, rax
.text:0000000000400BF0 call sub_400AAE
.text:0000000000400BF5
.text:0000000000400BF5 loc_400BF5: ; CODE XREF: sub_400BA9+37
.text:0000000000400BF5 mov rax, [rbp+var_10]
.text:0000000000400BF9 add rax, 8
.text:0000000000400BFD mov rax, [rax]
.text:0000000000400C00 lea rsi, aDecr ; "decr"
.text:0000000000400C07 mov rdi, rax
.text:0000000000400C0A call sub_400370
.text:0000000000400C0F test eax, eax
.text:0000000000400C11 jnz short loc_400C18
.text:0000000000400C13 call sub_400B39
.text:0000000000400C18
.text:0000000000400C18 loc_400C18: ; CODE XREF: sub_400BA9+68
.text:0000000000400C18 mov eax, 0
.text:0000000000400C1D leave
.text:0000000000400C1E retn
.text:0000000000400C1E sub_400BA9 endp
```

Looks like there is a ```cryp``` and a ```decr``` command line parameters. Assuming we need to decrypt the flag, we first need to find where the encrypted flag is. Running with ```cryp``` parameter gives us a hint at what it looks like:

```sh
$ ./packed cryp h4ck1t{test}
The hardest part is overcome.
0x95, 0xc0, 0x90, 0x8e, 0xc5, 0x8f, 0x74, 0x31, 0x6b, 0x63, 0x34, 0x68,
```

The encrypted bytes look like this:

```
95 C0 90 8E C5 8F 74 31 6B 63 34 68 ......t1kc4h
```

So the ending is just the flag prefix, reversed. Luckily, the encrypted flag is embedded in the binary:

![img2.png](https://0xd13a.github.io/ctfs/hackit2017/rev150/img2.png)

Now let's analyze the decryption algorithm so that we could reproduce it:

```
.text:0000000000400B39 sub_400B39 proc near ; CODE XREF: sub_400BA9+6A
.text:0000000000400B39
.text:0000000000400B39 var_9 = byte ptr -9
.text:0000000000400B39 var_8 = dword ptr -8
.text:0000000000400B39 var_4 = dword ptr -4
.text:0000000000400B39
.text:0000000000400B39 push rbp
.text:0000000000400B3A mov rbp, rsp
.text:0000000000400B3D sub rsp, 10h
.text:0000000000400B41 lea rdi, byte_6B20A0
.text:0000000000400B48 call sub_417BB0
.text:0000000000400B4D mov [rbp+var_8], eax
.text:0000000000400B50 mov eax, [rbp+var_8]
.text:0000000000400B53 mov [rbp+var_4], eax
.text:0000000000400B56
.text:0000000000400B56 loc_400B56: ; CODE XREF: sub_400B39+6B
.text:0000000000400B56 cmp [rbp+var_4], 0
.text:0000000000400B5A js short loc_400BA6
.text:0000000000400B5C mov eax, [rbp+var_4]
.text:0000000000400B5F movsxd rdx, eax
.text:0000000000400B62 lea rax, byte_6B20A0
.text:0000000000400B69 movzx ecx, byte ptr [rdx+rax]
.text:0000000000400B6D mov eax, [rbp+var_8]
.text:0000000000400B70 sub eax, 1
.text:0000000000400B73 sub eax, [rbp+var_4]
.text:0000000000400B76 movsxd rdx, eax
.text:0000000000400B79 lea rax, byte_6B20A0
.text:0000000000400B80 movzx eax, byte ptr [rdx+rax]
.text:0000000000400B84 xor eax, ecx
.text:0000000000400B86 xor eax, 0FFFFFF80h
.text:0000000000400B89 mov [rbp+var_9], al
.text:0000000000400B8C mov eax, [rbp+var_4]
.text:0000000000400B8F movsxd rdx, eax
.text:0000000000400B92 lea rax, byte_6B20A0
.text:0000000000400B99 movzx ecx, [rbp+var_9]
.text:0000000000400B9D mov [rdx+rax], cl
.text:0000000000400BA0 sub [rbp+var_4], 1
.text:0000000000400BA4 jmp short loc_400B56
.text:0000000000400BA6 ; ---------------------------------------------------------------------------
.text:0000000000400BA6
.text:0000000000400BA6 loc_400BA6: ; CODE XREF: sub_400B39+21
.text:0000000000400BA6 nop
.text:0000000000400BA7 leave
.text:0000000000400BA8 retn
.text:0000000000400BA8 sub_400B39 endp
```

Essentially the algorithm reverses the flag, and then encodes the first part of it by XORing it with characters in the second part and with ```0x80```.

To decode it let's write a short script:

```python
data = bytearray(open("packed","rb").read())

off = 0xb20a0
out = ""

for x in range(0x30/2):
out += chr(data[off + x] ^ data[off + 0x30 - x - 1] ^ 0x80)

print (out + str(data[off + 0x30/2: off + 0x30]))[::-1]
```

The flag is ```h4ck1t{mor0ns_rel1es_on_p4ck3r5_vari0rs_d03sn0t}```:

```sh
$ python solve.py
h4ck1t{mor0ns_rel1es_on_p4ck3r5_vari0rs_d03sn0t}
```

Original writeup (https://0xd13a.github.io/ctfs/hackit2017/rev150/).