# **ROVM**
## Source code
```c!
int __fastcall main(int argc, const char **argv, const char **envp)
{
struct sigaction s; // [rsp+0h] [rbp-150h] BYREF
struct stat stat_buf; // [rsp+A0h] [rbp-B0h] BYREF
int fd; // [rsp+138h] [rbp-18h]
int fildes; // [rsp+13Ch] [rbp-14h]
void *v8; // [rsp+140h] [rbp-10h]
void *buf; // [rsp+148h] [rbp-8h]
__int64 savedregs; // [rsp+150h] [rbp+0h]
__int64 retaddr; // [rsp+158h] [rbp+8h]
memset(&s, 0, sizeof(s));
s.sa_flags = 4;
s.sa_handler = (__sighandler_t)handler;
sigaction(0xB, &s, 0LL);
buf = mmap((void *)0x1224000, 0x1000uLL, 7, 0x21, 0xFFFFFFFF, 0LL);
if ( buf == (void *)0xFFFFFFFFFFFFFFFFLL )
{
perror("mmap failed");
exit(0);
}
fd = open("opcode", 0);
if ( fd == 0xFFFFFFFF )
{
perror("open failed");
exit(0);
}
if ( (unsigned int)fstat(fd, &stat_buf) == 0xFFFFFFFF )
{
perror("fstat failed");
exit(0);
}
if ( read(fd, buf, stat_buf.st_size) == 0xFFFFFFFFFFFFFFFFLL )
{
perror("read failed");
exit(0);
}
v8 = mmap((void *)0x1225000, 0x3000uLL, 7, 0x21, 0xFFFFFFFF, 0LL);
if ( v8 == (void *)0xFFFFFFFFFFFFFFFFLL )
{
perror("mmap failed");
exit(0);
}
fildes = open("chain", 0);
if ( fildes == 0xFFFFFFFF )
{
perror("open failed");
exit(0);
}
if ( (unsigned int)fstat(fildes, &stat_buf) == 0xFFFFFFFF )
{
perror("fstat failed");
exit(0);
}
if ( read(fildes, v8, stat_buf.st_size) == 0xFFFFFFFFFFFFFFFFLL )
{
perror("read failed");
exit(0);
}
savedregs = 0x1225000LL;
retaddr = 0x1224001LL;
return 0;
}
```
Phần đầu source code là xử lý tính hiệu segmentfault in 'Fail!'

Tiếp theo là đọc chain và opcode để thực hiện chương trình theo các file này.
## Hướng tiếp cận
Đầu tiên em đọc sơ về flow của chương trình, em nhận thấy register *rcx* sẽ tăng 1 đúng theo length của đầu vào.

Nhận thấy là chương trình vẫn đếm '/n'.
Với nhiều lần chạy thử em nhận thấy, chương trình khi length ở 0x24 có xuất hiện *$* (cũng chính là 0x24) trong rsp, em nghĩ đây có thể là đang check chiều dài của xâu. Và đúng vậy khi cho xâu dài 0x23 (tính thêm '\n') nó đã dẫn chương trình tới phần khác.

Ta nhận thấy đoạn code đầu là dùng để xóa '\n' cho xâu input.


Sau đó là đoạn chương trình chính để check flag như sau:
Đầu tiên chúng ta khởi tạo giá trị 0xfb

Ta có xử lý trên các byte của xâu nhập vào, ta thấy là chương trình lấy lần lượt các byte này nhân với các byte ở vị trí *0x1224950*


Kiểm tra ở vị trí *0x1224950*

Sau đó ta lấy tích đó chia cho *0xfb*, phần dư được lưu trong rdx sau đó ta lấy nó trừ 1.

Sau đó ta thấy mình sẽ dùng kết quả đó đem nhân cho 8, tiếp theo rsp sẽ tiếp tục cộng cho tích này. Như hàm check length kết quả này cần bằng 0 để không dính lỗi segmentfault.

Vậy là chúng ta cần làm vậy với tất cả byte trong input (gọi nó là s) và tương ứng với các byte ở vị trí *0x1224950* (em gọi nó là enc)
Vậy là chúng ta đã hình thành được các điều kiện đủ bao gồm 2 phần:
Chiều dài thõa mãn: Cần bằng 0x23 (cộng thêm '\n' là 0x24).
Nội dung thõa mãn: Tìm s[i] sao cho (enc[i]*s[i])%0xfb dư 1.
## Script:
```python!
import numpy as np
enc = [0x96,0x44,0x5b,0x25,0x47,0x8c,0x59,0x25,
0x92,0x5a,0x25,0x41,0xf0,0x44,0x27,0xf0,
0x8c,0x4c,0x4c,0x29,0x59,0x27,0x25,0x29,
0x2c,0x59,0x27,0x76,0x8c,0x27,0x5a,0x25,
0x29,0xc7,0x29] #0x000000000029c729
key = 0xfb
#print(len(enc))
dem =0
for i in enc:
for j in range(1,key):
x = (i*j)%key
if(x==1):
dem=dem+1 #đếm để kiểm tra chương trình đúng chưa
print(chr(j),end="")
break
```

flag: R0P_c4n_b5_pr0gr4mm1ng_1angu4g5_1o1
