This writeup contains the challenges that I authored and were hosted on finals and were categorized in Reverse Engineering!
## REVERSE ENGINEERING
### Easy : REbasic

First looking at readable strings using `rabin2` with the command:
```
rabin2 -z rebasic
```

We have some useful strings here, and also we can see that we have a string that is even more interesting saying : `/tmp/flag.txt`.
Running the binary asks for a secret, if the secret is not correct it'll say **JOB NOT DONE**, and if it's correct it'll say **JOB DONE**. We now use `radare2` to understand how the logic works.

we have two functions, namely `main` and `sym.mdcheck`. Taking a look at the main function:

it takes the secret, then it calls the function `sym.mdcheck` where it passes the secret to. Now taking a look at the `sym.mdcheck` function :

now we can see that `var_38h` takes the argument that is passed from the main function and we can see that `var_28h` and `var_24h` adds up to having `tzcert`, the we have a string `IfileGoBRR_now` that is then compared with our input , as seen earlier in the strings we also saw `IfileGoBRR_now`. This makes the password be `IfileGoBRR_now`.
Moving forward understanding the logic we can see that it's xorring each byte of our secret with `tzcert` then outputs the answer in `/tmp/flag.txt`

Giving it a try:

so the clear-text output is `3o-RR_now` where as the flag would be:
**FLAG**
```
tzcert{3o-RR_now}
```
### Easy : ZeroLog

Opening the APK file in `jadx-gui` allows me to get a clear read on the source code and all important files of the apk application. Taking a quick look at the source code for the file `MainActivity` we get a that it's performing validation of the username and password:

the password is in base64, decoding the password should provide us with the flag:

**FLAG**
```
tzcert{Mobile_login_app_with_b64}
```
### Medium : 13 Puzzles

I will be using Cutter and Ghidra to analyze this, first in the main function it asks for an input that is a quote:

And then creates a new string reader object :

After creating the new string reader, it passes the output of the string reader which contains our input to `sym.go.main.checkOutput`

Taking a look at this function in Ghidra we can see that the input is being compared with the string `e0g.....`

And then passes it to a new string builder and into another function that for some reason it shows as hex instead of the function's name as address, the function is `puzzleReader`
```cpp!
void sym.go.main.__puzzleReader_.Read(int64_t arg1)
{
uint8_t uVar1;
code *pcVar2;
uint64_t arg1_00;
int64_t *in_RAX;
uint64_t arg2;
undefined8 unaff_RBX;
undefined *puVar3;
undefined *unaff_RBP;
uint64_t unaff_RDI;
int64_t unaff_R14;
do {
puVar3 = (undefined *)*(undefined **)0x20;
if (*(undefined **)(uint64_t *)(unaff_R14 + 0x10) <= *(undefined **)0x20 &&
(undefined *)*(undefined **)0x20 != *(undefined **)(uint64_t *)(unaff_R14 + 0x10)) {
puVar3 = (undefined *)((int64_t)*(undefined **)0x20 + -0x28);
*(undefined **)((int64_t)*(undefined **)0x20 + -8) = unaff_RBP;
unaff_RBP = (undefined *)((int64_t)*(undefined **)0x20 + -8);
*(undefined8 *)((int64_t)*(undefined **)0x20 + 0x10) = unaff_RBX;
*(uint64_t *)((int64_t)*(undefined **)0x20 + 0x20) = unaff_RDI;
*(int64_t *)((int64_t)*(undefined **)0x20 + 0x18) = arg1;
pcVar2 = *(code **)(*in_RAX + 0x18);
*(undefined8 *)((int64_t)*(undefined **)0x20 + -0x30) = 0x49c914;
arg1 = (*pcVar2)();
arg2 = *(uint64_t *)((int64_t)*(undefined **)0x20 + 0x20);
if ((uint64_t)arg1 <= arg2) {
arg2 = *(uint64_t *)((int64_t)*(undefined **)0x20 + 0x10);
arg1_00 = *(uint64_t *)((int64_t)*(undefined **)0x20 + 0x18);
unaff_RDI = 0;
while( true ) {
if (arg1 <= (int64_t)unaff_RDI) {
return;
}
if (arg1_00 <= unaff_RDI) break;
uVar1 = *(uint8_t *)(arg2 + unaff_RDI);
if (uVar1 != 0x20) {
if (uVar1 < 0x6e) {
*(uint8_t *)(arg2 + unaff_RDI) = uVar1 + 0xd;
} else {
*(uint8_t *)(arg2 + unaff_RDI) = uVar1 - 0x2d;
}
}
unaff_RDI = unaff_RDI + 1;
}
*(undefined8 *)((int64_t)*(undefined **)0x20 + -0x30) = 0x49c977;
arg1 = sym.go.runtime.panicIndex(arg1_00);
}
*(undefined8 *)((int64_t)*(undefined **)0x20 + -0x30) = 0x49c97f;
in_RAX = (int64_t *)sym.go.runtime.panicSliceAcap(arg1, arg2);
}
*(int64_t **)(puVar3 + 8) = in_RAX;
*(undefined8 *)(puVar3 + 0x10) = unaff_RBX;
*(int64_t *)(puVar3 + 0x18) = arg1;
*(uint64_t *)(puVar3 + 0x20) = unaff_RDI;
*(undefined8 *)(puVar3 + -8) = 0x49c999;
sym.go.runtime.morestack_noctxt();
in_RAX = *(int64_t **)(puVar3 + 8);
unaff_RBX = *(undefined8 *)(puVar3 + 0x10);
arg1 = *(int64_t *)(puVar3 + 0x18);
unaff_RDI = *(uint64_t *)(puVar3 + 0x20);
*(undefined **)0x20 = (BADSPACEBASE *)puVar3;
} while( true );
}
```
Reading through this function I can see that it checks if the bytes of the string is not 32 then it continues by checking if it's greater than 109 if so then it subtracts 123 to each byte, then the bytes of the string will be (13 - bytes substracted with 123) + 65. If that condition isn't reached then each byte will be shifted ahead by 13:
```
while( true ) {
if (arg1 <= (int64_t)unaff_RDI) {
return;
}
if (arg1_00 <= unaff_RDI) break;
uVar1 = *(uint8_t *)(arg2 + unaff_RDI);
if (uVar1 != 0x20) {
if (uVar1 < 0x6e) {
*(uint8_t *)(arg2 + unaff_RDI) = uVar1 + 0xd;
} else {
*(uint8_t *)(arg2 + unaff_RDI) = uVar1 - 0x2d;
}
}
unaff_RDI = unaff_RDI + 1;
}
```
In a common cryptography cipher logic this is rot 13. Thus we have many ways to solving this, to mention a few;
1. writing a script

2. using online decoders

**FLAG**
```
tzcert{r0t13_g0_g4m3_puZZLE_with_MeE}
```
### Medium : Auth

Running the program it asks for a code, when I insert a wrong code,there comes a loop of error prompts:

Open the binary on any disassembler, in the main function, you shall get that there is quite a number of loops:

Reading through you come across where your input is being compared with `0x539`. Trying to input this as your passcode will provide the following:


means we need to get the decimal output of `0x539` which equals `839` running this in, will go through each loop until the stack is greater than `0xffffffe` then it'll give a hexadecimanl string

reading the code you shall find that there is a error that can occur on the stack if the variable `uStack180` is greater than `0xfffffffe`, Now then let's try running the binary with our input as the decimal of `0x539` and see what we get:

The string looks like decimal except there is an `0a` at the end so the next step is to try to decode this string, trying to decode it from decimal wont work so easy way is to try decode from hex. Decoding it should return another hex.

Decoding it again will give us the flag:

**FLAG**
```
tzcert{RuST_r3VER51NG_GOES_BRRR}
```
OOPS WE END HERE FOR NOW :)
---
<div style="width:100%"><div style="height:0;padding-bottom:56.25%;position:relative;width:100%"><iframe allowfullscreen="" frameBorder="0" height="100%" src="https://giphy.com/embed/KpJ47gKe6b7v7xQyWj/video" style="left:0;position:absolute;top:0" width="100%"></iframe></div></div>