# Ransomware
*this is solved after score board freeze*
這題裡面包含 `1~143.jpg`, `wannaSleep.exe`, `readme.txt`, `ransomware.jpg`
decompile wannaSleep 後可以看到一個 function
**FUN_0040177b**
```cpp=
void FUN_0040177b(LPCSTR param_1,LPCSTR param_2)
{
BOOL BVar1;
DWORD local_26c;
_WIN32_FIND_DATAA local_268;
CHAR local_128 [272];
HANDLE local_18;
HANDLE local_10;
PathCombineA(local_128,param_1,param_2);
local_10 = FindFirstFileA(local_128,(LPWIN32_FIND_DATAA)&local_268);
if (local_10 != (HANDLE)0xffffffffffffffff) {
do {
if ((local_268.dwFileAttributes & 0x10) == 0) {
PathCombineA(local_128,param_1,local_268.cFileName);
printf_s("%s\n",local_128);
FUN_00401560(local_128);
}
BVar1 = FindNextFileA(local_10,(LPWIN32_FIND_DATAA)&local_268);
} while (BVar1 != 0);
FindClose(local_10);
}
local_18 = CreateFileA("ransomeware.jpg",0x10000000,0,(LPSECURITY_ATTRIBUTES)0x0,1,0x80,
(HANDLE)0x0);
if (local_18 != (HANDLE)0xffffffffffffffff) {
WriteFile(local_18,&JPEG_00408040,DAT_004660b4,&local_26c,(LPOVERLAPPED)0x0);
CloseHandle(local_18);
}
return;
}
```
可以看到 PathCombineA 然後 FindFirstFileA
接著在 while loop 中 call FUN_00401560 然後 FindNextFileA
=> 一個把所有檔案加密的循環
**FUN_00401560**
```cpp=
void FUN_00401560(LPCSTR param_1)
{
DWORD local_2c;
LPVOID file_buf;
uint allocate_size;
DWORD file_size;
HANDLE file_fp;
uint local_10;
uint offset;
file_fp = CreateFileA(param_1,0x10000000,0,(LPSECURITY_ATTRIBUTES)0x0,3,0x80,(HANDLE)0x0);
if (file_fp != (HANDLE)0xffffffffffffffff) {
file_size = GetFileSize(file_fp,(LPDWORD)0x0);
allocate_size = (file_size & 0xfffff000) + 0x1000;
file_buf = VirtualAlloc((LPVOID)0x0,(ulonglong)allocate_size,0x3000,4);
ReadFile(file_fp,file_buf,file_size,&local_2c,(LPOVERLAPPED)0x0);
offset = ((allocate_size + file_size +
(int)*(char *)((longlong)file_buf + 0xc0U % (ulonglong)file_size)) % 0x4000_const +
(int)*(char *)((longlong)file_buf + 0xc79U % (ulonglong)file_size)) % 0x4000_const;
local_10 = 0;
while (local_10 < allocate_size) {
*(byte *)((longlong)file_buf + (longlong)(int)local_10) =
*(byte *)((longlong)file_buf + (longlong)(int)local_10) ^
(&xor_arr)[offset % 0x4000_const];
local_10 = local_10 + 1;
offset = offset + 1;
}
SetFilePointer(file_fp,0,(PLONG)0x0,0);
WriteFile(file_fp,file_buf,allocate_size,&local_2c,(LPOVERLAPPED)0x0);
VirtualFree(file_buf,0,0x8000);
CloseHandle(file_fp);
}
return;
}
```
可以看到把原檔案讀進來 計算 new size 跟 offset
用檔案跟 xor_arr xor 寫到新檔案
**recover file**
jpg 前 4 byte 是 magic number `0xff` `0xd8` `0xff` `0xe0`
利用加密後的前 4 byte 嘗試 xor 不同 offset 的 xor_arr
就能找到 offset 把檔案還原
```cpp=
void extract(string filename, char *xor_buf, int offset) {
fstream in(filename, fstream::in | fstream::binary);
fstream out("e" + filename, fstream::out | fstream::binary);
char c;
while(in.get(c)){
out.put((char)(xor_buf[offset] ^ c));
offset = (offset + 1) % 0x4000;
}
in.close();
out.close();
}
int main() {
fstream game_bin("wannaSleep.exe", fstream::in | fstream::binary);
game_bin.seekg(0x2620);
char buf[0x4000];
game_bin.read(buf, 0x4000);
for(int i = 1; i < 144; i++) {
string filename = to_string(i) + ".jpg";
cout << filename << '\n';
fstream file_bin(filename, fstream::in | fstream::binary);
char filebuf[4];
file_bin.read(filebuf, 0x4);
int target[] = {0xff, 0xd8, 0xff, 0xe0};
int know_offset;
for (int offset = 0; offset < 0x4000; offset++) {
if(((char)(filebuf[0] ^ buf[offset])) != (char)target[0]) {
continue;
}
if(((char)(filebuf[1] ^ buf[(offset + 1) % 0x4000])) != (char)target[1]) {
continue;
}
if(((char)(filebuf[2] ^ buf[(offset + 2) % 0x4000])) != (char)target[2]) {
continue;
}
if(((char)(filebuf[3] ^ buf[(offset + 3) % 0x4000])) != (char)target[3]) {
continue;
}
cout << "yeah" << '\n';
know_offset = offset;
break;
}
file_bin.close();
extract(filename, buf, know_offset);
}
game_bin.close();
}
```
解出來是 flag 拼圖 能用 python 拔掉 padding byte 但其實沒啥意義
txt 沒有 magic number 但推測其大小不會剛好 0x1000
加密會在後面有 padding 0x0
所以最後面會等於 xor_arr, 比對後就能找出 offset 4432
用前面的 extract 解
解出來是
>Sort them by size to get the right order,
>and there are 11*13 pieces of images.
>.PIL may save your life
然後照檔案大小排序後能發現 就是數字排序大到小
然後來拼圖 我用 opencv
```python=
import cv2
import numpy as np
canvas = np.zeros((80 * 13, 80 * 11, 3), np.uint8)
for i in range(143):
img = cv2.imread(f"e{143 - i}.jpg")
img = cv2.resize(img, (80, 80))
canvas[(i // 11) * 80: ((i // 11) + 1) * 80,
(i % 11) * 80: ((i % 11) + 1) * 80, :] = img
cv2.imwrite("pic.jpg", canvas)
```
然後手抄 flag 一直抄錯 ==

###### tags: `solved`