# Simple Reverse - 0x28(2023 Lab - Super Angry)
## Source code
:::spoiler main function
```cpp
__int64 __fastcall main(int argc, char **argv, char **a3)
{
__int64 *user_input; // rcx
__int64 v5; // rdx
__int64 v6; // rdx
char output[128]; // [rsp+10h] [rbp-B0h] BYREF
__int64 user_input_cp[6]; // [rsp+90h] [rbp-30h] BYREF
user_input_cp[5] = __readfsqword(0x28u);
if ( argc == 2 )
{
user_input = (__int64 *)argv[1];
v5 = user_input[1];
user_input_cp[0] = *user_input;
user_input_cp[1] = v5;
v6 = user_input[3];
user_input_cp[2] = user_input[2];
user_input_cp[3] = v6;
scramble_fn((__int64)user_input_cp, output, 0x20uLL);
if ( !memcmp(output, verify_key, 0x80uLL) )
puts("Correct!");
else
puts("Incorrect!");
return 0LL;
}
else
{
printf("Usage: %s <input>\n", *argv);
return 1LL;
}
}
```
:::
:::spoiler scramble function
```cpp
unsigned __int64 __fastcall scramble_fn(char *user_input, uint32_t *output, unsigned __int64 const_0x20)
{
unsigned __int64 result; // rax
int cmd; // [rsp+24h] [rbp-Ch]
unsigned __int64 i; // [rsp+28h] [rbp-8h]
cmd = 1;
memset(output, 0, 4 * const_0x20); // 從這邊可以看得出來output的大小應該是int或是uint,因為有4 bytes
for ( i = 0LL; ; ++i )
{
result = i;
if ( i >= const_0x20 )
break;
switch ( cmd )
{
case 1:
output[i] = (user_input[i] << 12) + 5308892;
cmd = 3;
break;
case 2:
output[i] = 4 * (user_input[i] + 1958409);
cmd = 4;
break;
case 3:
output[i] = user_input[i] + 192731;
cmd = 5;
break;
case 4:
output[i] = 4 * user_input[i] + 14474785;
cmd = 1;
break;
case 5:
output[i] = (user_input[i] << 17) + 176044;
cmd = 6;
break;
case 6:
output[i] = user_input[i] - 3874948;
cmd = 2;
break;
default:
continue;
}
}
return result;
}
```
:::
## Recon
可以從IDA解析出來的結果得知,這支程式的主要流程是我們執行的時候command多帶一個參數,而這個參數會直接進到scramble_fn做一些操作,最後會再跟verify_key進行memcmp,大略分析一下scramble_fn後發先他是一個偏簡單但我們懶得看得操作,所以可以試看看用angr解看看
angr基本流程:
1. 建立一個project
2. 建立claripy symbol - 以這個lab的例子來說就是建立我們輸入進去的程式的input string
3. 建立初始的state - 以這個lab來說就是我們一開始輸入的input string
4. 有了proj / symbol / initial state之後就要開始讓他跑起來
## Exploit
```python
import angr
import claripy
# 建立一個project
root = 'Reverse/Lab3/Super Angry/'
proj = angr.Project(root + 'super_angry')
# 建立Claripy Symbol
sym_arg = claripy.BVS('sym_arg', 8 * 32) # 就像z3一樣要建立symbol
# 建立初始的state
state = proj.factory.entry_state(args=[proj.filename, sym_arg])
simgr = proj.factory.simulation_manager(state)
# 有了proj/symbol/initial state之後就要開始讓他跑起來
simgr.explore(find = lambda s: b'Correct!' in s.posix.dumps(1))
if len(simgr.found) > 0:
print(simgr.found[0].solver.eval(sym_arg, cast_to=bytes))
else:
print("NONONONO")
# b'FLAG{knowing_how_2_angr!}\x00DBUS_S'
```
Flag: `FLAG{knowing_how_2_angr!}`