# Moon Angstrom
> Đề: 
*Lời đầu tiên cho em cảm ơn anh Mochi đã hỗ trợ em :>*
- Tải file [tại đây](https://github.com/Okoonzz/07.-Rev/blob/File/moon.zip)
- Bài này không thể nào đọc bằng code C được bởi file quá nặng chứa rất nhiều hàm cũng như các biến cục bộ.
- Phải đọc kĩ mới nhìn ra được cách chương trình này hoạt động cũng như thuật toán chính của bài này.

- Khi phân tích file ta thấy rằng file này có tới 1293 func. Mỗi func này có nhiệm vụ add một con số nào đó vào các code segment, nếu ta nhìn kĩ hơn thì các code segment này lưu cách nhau 8bytes. Và điều đặc biệt hơn đó là nó vẫn giữ địa chỉ các code segment này qua các hàm func. Vậy nên ta có thể xem nó như là một mảng và lần lượt cộng thêm lên một lượng nhất định qua từng func. Hàm này đặt tên là "check[i]".

- Phân tích đến hàm main, điều ta thấy đầu tiên ở đây là rất nhiều biến cục bộ được lưu trữ tại đây. Để quá trình phân tích dễ dàng hơn thì ta sẽ đổi lại tên một số biến cho dễ hình dung.

- Kể từ đây ta có thể nhìn ra được sau khi nhập một số nguyên nào đó vào thì sẽ có format chung trước mỗi số đó là "> số cần nhập". Sau khi nhập vào thì nó sẽ lưu 0 vào "[rbp+var_1440]" sau đó nhảy một cách vô điều kiện tới một hàm `"short loc_237D37E"`. Tiến hành kiểm tra xem hàm này chứa gì.

- Hàm này sẽ so sánh [rbp+var_1440] vừa được thêm 0 vào trước đó với input, nếu như nhỏ hơn sẽ nhảy vào `"short loc_237D36D"`. Ở hàm `"short loc_237D36D"` sẽ thực thi func0 (tức là nó sẽ add các phần tử của mảng "check" đã phân tích ở trên với một lượng nhất định) sau đó tăng thêm 1 cho `[rbp+var_1440]`. Cứ thế mà lặp đi lặp lại đến khi nào `[rbp+var_1440]` lớn hơn hoặc bằng giá trị nhập vào thì tiếp tục thực hiện việc nhập lần thứ 2. Công việc so sánh và cộng thêm này cứ thế cho đến hết 1293 hàm.

- Kiểm tra đến cuối cùng của hàm main ta thấy được sau khi cộng hết tất cả xong thì hàm `"loc_239A7EF"` sẽ kiểm tra lần lượt với data đã được set sẵn có tên `"needed"`.
- => Từ đó ta sẽ có được tổng quát bài toán trên đó là có 1293 biến tương ứng với 1293 hàm. Bài toán trở về bài toán vô cùng quen thuộc đó chính là hệ phương trình.
> Ta sẽ hình dung bài toán như sau:
>
> Giả sử ban đầu ta có các số nhất định: 5 10 và một dãy 4 8 và số ta cần kiểm tra cuối cùng là 9000, 10000. Lúc này:
> * Lần đầu tiên các số đã cho đó cộng với x lần
> * Lần tiếp theo sẽ cộng tiếp với y lần
> * ...
> * Cho đến khi nào bằng số 9000, 10000 thì xong
> * Tức là ta sẽ có:
> * 5x + 4y = 9000
> * 10x + 8y = 10000
> * => Tìm được (x,y) thỏa mãn
>
> **Lưu ý:** Đây chỉ là ví dụ dễ hình dung, không mang tính tìm ra được nghiệm hoàn toàn.
- Việc cuối cùng cần làm đó là viết script để lấy toàn bộ các hệ số ra và sau đó thực hiện giải hệ phương trình. Điều đáng chú ý hơn nữa, trong máy tính sẽ có 3 loại cộng đó là cộng bình thường, cộng bù 2 cuối cùng là lấy ra nhưng không làm gì rồi bỏ lại như cũ.
- Ở đây, có hai script. Đầu tiên là tham khảo của một anh bên BK:
```
from pwn import *
from capstone import *
program = ELF('./moon')
needed = []
for i in range(1293):
needed.append(int.from_bytes(program.read(program.sym['needed']+i*8, 8), 'little'))
check = []
for j in range(1293):
if j != 1292:
func = program.disasm(
program.sym[f'func{j}'], program.sym[f'func{j+1}']-program.sym[f'func{j}'])
else:
func = program.disasm(
program.sym['func1292'], program.sym['main']-program.sym['func1292'])
ins = func.split('\n')
eq = []
i = 3
while i < len(ins):
if 'mov' in ins[i] and 'add rax,' in ins[i+1] and 'mov' in ins[i+2]:
num = int(ins[i+1].split(',')[1], 16)
eq.append(num)
i = i + 3
elif 'mov' in ins[i] and 'sub rax,' in ins[i+1] and 'mov' in ins[i+2]:
num = 0xffffffffffffffff - int(ins[i+1].split(',')[1], 16) + 1
eq.append(num)
i = i + 3
elif 'mov' in ins[i] and 'mov' in ins[i+1]:
eq.append(0)
i = i + 2
else:
i = i + 1
check.append(eq)
```
> Cụ thể đoạn script trên lấy ra được `"needed"`. Ở đây phải lấy theo 8byte bởi nhìn vào IDA thì sẽ thấy được và cách lấy theo little. Tiếp đến lấy tất cả các instruction từ 1293 hàm và kiểm tra xem nó thuộc loại phép cộng nào như các phép cộng đã đề cập ở trên. Sau đó sẽ có được một ma trận việc cuối cùng là giải ma trận này.
- Đây là đoạn script thứ hai:
```
f = open(r"C:\Users\Admin\Downloads\moon", 'rb')
data = f.read()
adr = 0x11B6
mt = []
for i in range(1293):
mt.append([])
for i in range(1293):
adr += 0x0f
j = 0
while True:
if data[adr+1] == 0x05:
mt[j].append(int.from_bytes(
data[adr+2:adr+6], byteorder="little"))
adr += 0x14
elif data[adr+1] == 0x83:
mt[j].append(int.from_bytes(
data[adr+3:adr+4], byteorder='little'))
adr += 0x12
else:
mt[j].append(0)
adr += 0x0e
if int.from_bytes(data[adr-7:adr-4], byteorder='big') != 0x488b05:
break
j += 1
adr -= 0x04
neededBin = data[0x01FA8060:0x1faa8c8]
for i in range(0, len(neededBin), 8):
mt[i >> 3].append(int.from_bytes(neededBin[i:i+8], byteorder='little'))
csv = open("Sol.csv", "w")
csv.write('\n'.join([','.join([str(num) for num in row]) for row in mt]))
csv.close()
```
> Cụ thể ở đoạn script này sử dụng thẳng bytes. Chú ý rằng địa chỉ hàm đầu tiên bắt đầu từ *0x11B6*. Ta sẽ kiểm tra kĩ một tí đó là nếu như dữ liệu ở vị trí đã chỉ định có giá trị là *0x05* hoặc *0x83* thì sẽ lấy vào bởi ta chú ý như sau:
>
> 
>
> Ở đây ta thấy các ins add, kiểm tra bên hex view thì nó lúc nào cũng chưa *"05"* hoặc *"83"*
>
> 
>
> 
>
> Và sẽ kiểm tra thêm một điều kiện nữa đó chính là biên ở mỗi hàm nếu như trừ đi một lượng như trên scipt mà không phải *"0x488b05"* thì chắc chắn lúc này đã hết một func và tiến hành nhảy sang func khác.
> Nếu làm theo cách này còn một lỗi khá nghiêm trọng liên quan đến địa chỉ đó là địa chỉ virtual ngay tại `"needed"`. Nếu lấy địa chỉ như trong IDA thì sẽ sai. Nên lúc này để đảm bảo chính xác, ta phải kiểm tra xem bằng HEX để bắt được địa chỉ lưu `"needed"` từ đầu đến cuối.
>
> 
=> Ở đây, chủ yếu luyện kĩ năng lấy dữ liệu từ file khá hay. ^^