# try_me

Đọc code trong IDA:
+ Hàm start:
```C
void __fastcall __noreturn start(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v3; // rax
unsigned int v4; // esi
__int64 v5; // [rsp-8h] [rbp-8h] BYREF
void *retaddr; // [rsp+0h] [rbp+0h] BYREF
v4 = v5;
v5 = v3;
sub_80A200((__int64)sub_808ECB, v4, (__int64)&retaddr, 0LL, 0LL, a3, (__int64)&v5);
}
```
+ Hàm sub_808ECB:
```C
void sub_808ECB()
{
const char *v0; // [rsp+8h] [rbp-8h]
v0 = (const char *)sub_82EDC0(34LL);
sub_812F50((__int64)"%32s", v0);
if ( (unsigned __int64)sub_401190() <= 0x1F )
{
sub_812DC0((__int64)"Try HardeR");
sub_812290(1LL);
}
__asm { jmp rax }
}
```
Sau khi đọc code trong các hàm con thì mình có được:
+ `sub_812F50` là hàm nhập vào input của mình
+ `sub_812DC0` là hàm print
+ `sub_812290` là hàm exit
+ `sub_401190` là hàm lấy độ dài của v0, nghĩa là nếu nhập vào độ dài <= 0x1F (31) thì in ra "Try HardeR" và thoát.
Đặc biệt có một đoạn ở cuối IDA của mình đã không dịch được:
`__asm { jmp rax }`
Không biết vì sao nên mình thử dùng ghidra xem có ra hàm gì không:
```C
void FUN_00808ecb(void)
{
undefined8 uVar1;
ulong uVar2;
uVar1 = FUN_0082edc0(0x22);
FUN_00812f50(&UNK_008bd004,uVar1);
uVar2 = thunk_FUN_008314f0(uVar1);
if (uVar2 < 0x20) {
FUN_00812dc0(&UNK_008bd009);
FUN_00812290(1);
}
FUN_00401ad5(uVar1);
return;
}
```
Và đó là hàm `FUN_00401ad5` với đầu vào là input của mình:
+ `FUN_00401ad5`
Đầy là một hàm có kích thước quá lớn nên không thể decomplie được, nhưng vì chỉ có các thao tác ADD, XOR, SUB nên nếu cần thì có thể reverse được


Cuối hàm thì nó có gọi tới `FUN_00808e85`
<details open>
<summary>FUN_00808e85</summary>
```C
void FUN_00808e85(ulong param_1,undefined8 param_2,undefined8 param_3,undefined8 param_4,
int *param_5,undefined8 param_6)
{
long lVar1;
undefined8 extraout_RDX;
undefined8 uVar2;
uVar2 = 0;
lVar1 = FUN_0085f6f0(0,0,param_3,param_4,param_5,param_6);
if (lVar1 < 0) {
FUN_00808ca9(param_1,uVar2,extraout_RDX,param_4,param_5,param_6);
}
else {
FUN_00808d97(param_1,uVar2,extraout_RDX,param_4,param_5,param_6);
}
return;
}
//#################################################################
void FUN_00808ca9(ulong param_1,undefined8 param_2,undefined8 param_3,undefined8 param_4,
int *param_5,undefined8 param_6)
{
ulong uVar1;
ulong extraout_RDX;
ulong extraout_RDX_00;
ulong uVar2;
long in_FS_OFFSET;
int local_50;
int local_4c;
byte local_46 [54];
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
local_46[0xe] = 0x18;
local_46[0xf] = 0x35;
local_46[0x10] = 0x40;
local_46[0x11] = 0x7b;
local_46[0x12] = 0xbc;
local_46[0x13] = 0xd1;
local_46[0x14] = 0xea;
local_46[0x15] = 0xcf;
local_46[0x16] = 0x33;
local_46[0x17] = 0x4e;
local_46[0x18] = 0x50;
local_46[0x19] = 0xd1;
local_46[0x1a] = 0x1b;
local_46[0x1b] = 99;
local_46[0x1c] = 0xaa;
local_46[0x1d] = 0xc2;
uVar1 = 0x49e304c7a952867;
local_46[0x1e] = 0xe4;
local_46[0x1f] = 0xda;
local_46[0x20] = 0xaa;
local_46[0x21] = 0x49;
local_46[0x22] = 0xec;
local_46[0x23] = 0xcd;
local_46[0x24] = 0xf8;
local_46[0x25] = 0x5f;
local_46[0x26] = 0x67;
local_46[0x27] = 0x28;
local_46[0x28] = 0x95;
local_46[0x29] = 0x7a;
local_46[0x2a] = 0x4c;
local_46[0x2b] = 0x30;
local_46[0x2c] = 0x9e;
local_46[0x2d] = 4;
uVar2 = param_1;
for (local_50 = 0; local_50 < 0x20; local_50 = local_50 + 1) {
uVar1 = (ulong)*(byte *)(param_1 + (long)local_50);
if (*(byte *)(param_1 + (long)local_50) != local_46[(long)local_50 + 0xe]) {
uVar2 = 1;
FUN_00812290((undefined8 *)0x1);
uVar1 = extraout_RDX;
}
}
local_46[0] = 0x70;
local_46[1] = 0x58;
local_46[2] = 0x17;
local_46[3] = 0x44;
local_46[4] = 0x42;
local_46[5] = 0x55;
local_46[6] = 0x5a;
local_46[7] = 0x5e;
local_46[8] = 0x43;
local_46[9] = 0x17;
local_46[10] = 0x43;
local_46[0xb] = 0x5f;
local_46[0xc] = 0x5e;
local_46[0xd] = 0x44;
for (local_4c = 0; local_4c < 0xe; local_4c = local_4c + 1) {
uVar2 = (ulong)(uint)(int)(char)(local_46[local_4c] ^ 0x37);
FUN_00821830(local_46[local_4c] ^ 0x37,param_2,uVar1,param_4,param_5,param_6);
uVar1 = extraout_RDX_00;
}
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
FUN_008618b0(uVar2,param_2,uVar1,param_4,param_5,param_6);
}
return;
}
//#################################################################
void FUN_00808d97(ulong param_1,undefined8 param_2,undefined8 param_3,undefined8 param_4,
int *param_5,undefined8 param_6)
{
ulong uVar1;
ulong extraout_RDX;
ulong extraout_RDX_00;
ulong uVar2;
long in_FS_OFFSET;
int local_50;
int local_4c;
byte local_46 [54];
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
local_46[0xe] = 0x81;
local_46[0xf] = 0xb;
local_46[0x10] = 0xeb;
local_46[0x11] = 0x94;
local_46[0x12] = 0xbd;
local_46[0x13] = 0xb4;
local_46[0x14] = 0x58;
local_46[0x15] = 0x17;
local_46[0x16] = 0x50;
local_46[0x17] = 0xb5;
local_46[0x18] = 99;
local_46[0x19] = 0xd0;
local_46[0x1a] = 0xcb;
local_46[0x1b] = 0x62;
local_46[0x1c] = 0xaa;
local_46[0x1d] = 0x11;
uVar1 = 0x199e991e4f0c25c;
local_46[0x1e] = 0x77;
local_46[0x1f] = 0x87;
local_46[0x20] = 0xe9;
local_46[0x21] = 0x8e;
local_46[0x22] = 0xf;
local_46[0x23] = 0x5f;
local_46[0x24] = 0x19;
local_46[0x25] = 0xd9;
local_46[0x26] = 0x5c;
local_46[0x27] = 0xc2;
local_46[0x28] = 0xf0;
local_46[0x29] = 0xe4;
local_46[0x2a] = 0x91;
local_46[0x2b] = 0xe9;
local_46[0x2c] = 0x99;
local_46[0x2d] = 1;
uVar2 = param_1;
for (local_50 = 0; local_50 < 0x20; local_50 = local_50 + 1) {
uVar1 = (ulong)*(byte *)(param_1 + (long)local_50);
if (*(byte *)(param_1 + (long)local_50) != local_46[(long)local_50 + 0xe]) {
uVar2 = 1;
FUN_00812290((undefined8 *)0x1);
uVar1 = extraout_RDX;
}
}
local_46[0] = 0x70;
local_46[1] = 0x58;
local_46[2] = 0x17;
local_46[3] = 0x44;
local_46[4] = 0x42;
local_46[5] = 0x55;
local_46[6] = 0x5a;
local_46[7] = 0x5e;
local_46[8] = 0x43;
local_46[9] = 0x17;
local_46[10] = 0x43;
local_46[0xb] = 0x5f;
local_46[0xc] = 0x5e;
local_46[0xd] = 0x44;
for (local_4c = 0; local_4c < 0xe; local_4c = local_4c + 1) {
uVar2 = (ulong)(uint)(int)(char)(local_46[local_4c] ^ 0x37);
FUN_00821830(local_46[local_4c] ^ 0x37,param_2,uVar1,param_4,param_5,param_6);
uVar1 = extraout_RDX_00;
}
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
FUN_008618b0(uVar2,param_2,uVar1,param_4,param_5,param_6);
}
return;
}
```
</details>
Đến đây thì có thể đoán được chương trình sẽ đem input của mình qua một đống ADD, SUB, XOR sau đó chạy hàm này để check với một mảng hằng ở một trong hai hàm trên kia.
Chạy thử với hàm hai hàm trên mà bỏ qua đoạn check input:
<details open>
<summary>FUN_00808e85</summary>
```C
#include <bits/stdc++.h>
using namespace std;
#define int long long
int local_46[54];
void FUN_00808ca9(int input[]) {
local_46[0xe] = 0x18;
local_46[0xf] = 0x35;
local_46[0x10] = 0x40;
local_46[0x11] = 0x7b;
local_46[0x12] = 0xbc;
local_46[0x13] = 0xd1;
local_46[0x14] = 0xea;
local_46[0x15] = 0xcf;
local_46[0x16] = 0x33;
local_46[0x17] = 0x4e;
local_46[0x18] = 0x50;
local_46[0x19] = 0xd1;
local_46[0x1a] = 0x1b;
local_46[0x1b] = 99;
local_46[0x1c] = 0xaa;
local_46[0x1d] = 0xc2;
local_46[0x1e] = 0xe4;
local_46[0x1f] = 0xda;
local_46[0x20] = 0xaa;
local_46[0x21] = 0x49;
local_46[0x22] = 0xec;
local_46[0x23] = 0xcd;
local_46[0x24] = 0xf8;
local_46[0x25] = 0x5f;
local_46[0x26] = 0x67;
local_46[0x27] = 0x28;
local_46[0x28] = 0x95;
local_46[0x29] = 0x7a;
local_46[0x2a] = 0x4c;
local_46[0x2b] = 0x30;
local_46[0x2c] = 0x9e;
local_46[0x2d] = 4;
// for (int i = 0; i < 0x20; ++i) {
// if (input[i] != local_46[i + 0xe]) {
// exit(0);
// }
// }
local_46[0] = 0x70;
local_46[1] = 0x58;
local_46[2] = 0x17;
local_46[3] = 0x44;
local_46[4] = 0x42;
local_46[5] = 0x55;
local_46[6] = 0x5a;
local_46[7] = 0x5e;
local_46[8] = 0x43;
local_46[9] = 0x17;
local_46[10] = 0x43;
local_46[0xb] = 0x5f;
local_46[0xc] = 0x5e;
local_46[0xd] = 0x44;
string t = "";
for (int i = 0; i < 0xe; ++i)
t += char(local_46[i] ^ 0x37);
cout << t;
return;
}
void FUN_00808d97(int input[]) {
local_46[0xe] = 0x81;
local_46[0xf] = 0xb;
local_46[0x10] = 0xeb;
local_46[0x11] = 0x94;
local_46[0x12] = 0xbd;
local_46[0x13] = 0xb4;
local_46[0x14] = 0x58;
local_46[0x15] = 0x17;
local_46[0x16] = 0x50;
local_46[0x17] = 0xb5;
local_46[0x18] = 99;
local_46[0x19] = 0xd0;
local_46[0x1a] = 0xcb;
local_46[0x1b] = 0x62;
local_46[0x1c] = 0xaa;
local_46[0x1d] = 0x11;
local_46[0x1e] = 0x77;
local_46[0x1f] = 0x87;
local_46[0x20] = 0xe9;
local_46[0x21] = 0x8e;
local_46[0x22] = 0xf;
local_46[0x23] = 0x5f;
local_46[0x24] = 0x19;
local_46[0x25] = 0xd9;
local_46[0x26] = 0x5c;
local_46[0x27] = 0xc2;
local_46[0x28] = 0xf0;
local_46[0x29] = 0xe4;
local_46[0x2a] = 0x91;
local_46[0x2b] = 0xe9;
local_46[0x2c] = 0x99;
local_46[0x2d] = 1;
// for (int i = 0; i < 0x20; ++i) {
// if (input[i] != local_46[i + 0xe]) {
// exit(0);
// }
// }
local_46[0] = 0x70;
local_46[1] = 0x58;
local_46[2] = 0x17;
local_46[3] = 0x44;
local_46[4] = 0x42;
local_46[5] = 0x55;
local_46[6] = 0x5a;
local_46[7] = 0x5e;
local_46[8] = 0x43;
local_46[9] = 0x17;
local_46[10] = 0x43;
local_46[0xb] = 0x5f;
local_46[0xc] = 0x5e;
local_46[0xd] = 0x44;
string t = "";
for (int i = 0; i < 0xe; ++i)
t += char(local_46[i] ^ 0x37);
cout << t;
return;
}
signed main() {
int input[0x20] = {};
FUN_00808ca9(input);
cout << '\n';
FUN_00808d97(input);
getchar();
return 0;
}
```
</details>
Cả 2 hàm đều ra cùng kết quả:
```
Go submit this
Go submit this
```
Vậy mình sẽ reverse cả 2 hàm :v bằng cách lấy local_46[0xe..0x2d] đi ngược lên theo đống ADD, SUB, XOR trong hàm FUN_00401ad5 để ra input.
Hàm đó thực sự quá dài (>4e6 dòng) để có thể copy ra, nên mình sẽ dùng lệnh dump ra lưu vào file:
```dump verilog memory result.bin 0x00401adf 0x00808c9c```
Sai lầm nằm ở đây khi thay vì dump code assembly để cho có lệnh rõ ràng thì mình lại dump dạng hex rồi phải đi mò và thêm đống bug sau đó (vì tự nhiên có hàm chen vô giữa)
Các lệnh đều có dạng:
`<typ> byte ptr [RAX + <pos>], <val>`
Dựa và hexdump thì:
+ Mở đầu là 0x80
+ Nếu là loại thao tác với [RAX] (vị trí 0) thì đi theo sau là typ, val
+ Còn không thì theo sau là typ, pos, val
Code python:
``` python
f = open("result.bin", "r").read().split()
s = [0x81, 0xb, 0xeb, 0x94, 0xbd, 0xb4, 0x58, 0x17, 0x50, 0xb5, 99, 0xd0, 0xcb, 0x62, 0xaa, 0x11, 0x77, 0x87, 0xe9, 0x8e, 0xf, 0x5f, 0x19, 0xd9, 0x5c, 0xc2, 0xf0, 0xe4, 0x91, 0xe9, 0x99, 1]
stack = []
for i in range(len(f) - 1, -1, -1):
x = int(f[i], 16)
if x == 0x80:
if len(stack) == 3:
val = stack[-3]
pos = stack[-2]
typ = stack[-1]
stack = []
elif len(stack) == 2:
val = stack[-2]
pos = 0
typ = stack[-1]
stack = []
if typ == 0x00 or typ == 0x40:
s[pos] = (s[pos] - val + 128) % 128
elif typ == 0x68 or typ == 0x28:
s[pos] = (s[pos] + val) % 128
else:
s[pos] ^= val
s[pos] %= 128
else:
stack.append(x)
for i in s:
print(chr(i), end = '')
```
Bug bắt đầu từ đây:
+ Nhận ra 0x80 chưa chắc là bắt đầu của lệnh mới vì nó cúng có thể là một val
+ Lúc chạy thì bị lỗi tràn mảng, chỉ có thể là do pos tràn trong s[pos], mà sao tràn được, chắc là so sai format :v. Code in đoạn in ra địa chỉ để xem nó lỗi từ chỗ nào thì phát hiện ra ngay giữ đoạn code dài thì lại lọt vào một hàm khác (không chỉ 1 mà còn nhiều hàm khác).

cũng may các hàm này không có giá trị 0x80 :v
+ Vì có hàm chen vào giữ nên sau khi cho chạy qua hàm đó thì không thể biết được truy vấn tiếp theo là loại nào trong 2 loại trên (vì không thể xét độ dài 2 hay 3 nữa), vả lắm rồi nên phải chơi if test…
Code in được kết quả:
```python
# import sys
# sys.stdout = open("output.txt", 'w')
f = open("result.bin", "r").read().split()
s = [0x81, 0xb, 0xeb, 0x94, 0xbd, 0xb4, 0x58, 0x17, 0x50, 0xb5, 99, 0xd0, 0xcb, 0x62, 0xaa, 0x11, 0x77, 0x87, 0xe9, 0x8e, 0xf, 0x5f, 0x19, 0xd9, 0x5c, 0xc2, 0xf0, 0xe4, 0x91, 0xe9, 0x99, 1]
stack = []
cnt = 0
id = 0x00808c98 + 4
for i in range(len(f) - 1, -1, -1):
x = int(f[i], 16)
id -= 1
if x == 0x80:
if len(stack) == 3:
val = stack[-3]
pos = stack[-2]
typ = stack[-1]
stack = []
elif len(stack) == 2:
val = stack[-2]
pos = 0
typ = stack[-1]
stack = []
elif len(stack) < 2: # (**1)
stack.append(x)
if len(stack) > 3:
stack = stack[1:]
continue
if id == 0x004cee81: # (**3)
val = pos
pos = 0
if typ == 0x00 or typ == 0x40:
s[pos] = (s[pos] - val + 128) % 128
print(f'{hex(id)} ADD [RAX + {hex(pos)}], {hex(val)}')
elif typ == 0x68 or typ == 0x28:
s[pos] = (s[pos] + val) % 128
print(f'{hex(id)} SUB [RAX + {hex(pos)}], {hex(val)}')
else:
s[pos] ^= val
s[pos] %= 128
print(f'{hex(id)} XOR [RAX + {hex(pos)}], {hex(val)}')
else:
stack.append(x)
if len(stack) > 3: # (**2)
stack = stack[1:]
for i in s:
print(chr(i), end = '')
```
Kết quả:

