[Writeup] [ASIS CTF] Cryptor (Crypto200)

Standard

We have found the cryptor source code. Decrypt the file.
files
File dự phòng: cryptor.zip

Nội dung chính

Với bài này, chúng ta được nhận 2 file là flag.png_Cryptedcryptor.cpp. Nội dung file cryptor.cpp như sau:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

using namespace std;
int bitXor(int, int);

int main(int argc, char **argv)
{
	srand(time(NULL));
	char *path=new char[30];
	if(argc > 1)
		path = argv[1];
	else
	{
		printf("\nenter file\n");
		scanf("%s",path);
	}
	int g = rand() % 512 + 32;
	int n = rand() % g;
	int mask = rand() % 256;
	FILE *inFile = fopen(path, "rb");
	FILE *outFile = fopen(strcat(path, "_Crypted"), "wb");
	if(inFile == NULL || outFile == NULL)
	{
		printf("Error\ncant read/write file\n");
		return 1;
	}
	unsigned char H, L;
	unsigned char *readBuffer = new unsigned char[g], *writeBuffer = new unsigned char[g];
	while(!feof(inFile))
	{
		int len = fread(readBuffer, 1, g, inFile);
		if(len < g)
			fwrite(readBuffer , 1 , len , outFile);
		else
		{
			for(int i = 0 ; i < g ; i++)
			{
				int nIndex = i + n;
				int pIndex = i - n;
				if(nIndex >= g)
					nIndex -= g;
				if(nIndex < 0)
					nIndex += g;
				if(pIndex >= g)
					pIndex -= g;
				if(pIndex < 0)
					pIndex += g;
				H = readBuffer[nIndex] / 16;
				L = readBuffer[pIndex] % 16;
				writeBuffer[i] = bitXor(16 * H + L, mask);
			}
			fwrite(writeBuffer , 1 , g , outFile);
		}
	}
	fclose (inFile);
	fclose (outFile);
	printf("\nsave decryption code: %d.%d.%d\n", g, n, mask);
	return 0;
}

int bitXor(int x, int y)
{
    int a = x & y;
    int b = ~x & ~y;
    int z = ~a & ~b;
    return z;
}

Code không phức tạp, tuy nhiên dễ thấy là chúng ta cần phải xác định được g, nmask thì mới có thể giải mã được file flag.png_Crypted.

Xét lại thuật toán mã hóa, đặt tên file gốc là A và file sau khi mã hóa là B. Khi đó, với mỗi mảng byte có kích thước g, byte thứ i của B được tính dựa trên 2 byte thứ (i – n) và (i + n) của A, có xoay vòng nếu index nằm ngoài mảng. Hình sau minh họa với g = 10, n = 3:

01-09-2013 17-58-34

Theo hình trên, byte thứ 4 của B được tính dựa trên byte thứ 1 và byte thứ 7 của A, và byte thứ 8 của B được tính dựa trên byte thứ 5 và byte thứ 1 của A (8 + 3 = 11 vượt kích thước mảng, nên quay vòng về 1).

Cũng với cách giải thích như vậy, thấy ngay được rằng ở quá trình giải mã, khi đã có file B, thì byte thứ 1 của file A sẽ tính dựa trên byte thứ 4 (1 + 3) và byte thứ 8 (1 – 3, xoay vòng) của file B, với thứ tự bit thấp – bit cao bị hoán đổi.

Mặt khác, ta biết rằng file gốc có định dạng .png, với chữ ký là:

89 50 4E 47 0D 0A 1A 0A           ‰PNG....

nên hoàn toàn có thể tìm được g, nmask (do toàn bộ output và 8 byte đầu của input đều đã xác định). Ngoài ra, để tối ưu tốc độ, ta có thể tính ngay mask dựa trên 1 trong 8 byte bất kỳ đã biết, thay vì mất thêm một vòng lặp nữa.

Đoạn code sau sẽ giúp ta xác định 3 tham số cần tìm:

def get_pos(i, n, g):
	i = i + n
	if i >= g:
		i -= g
	if (i < 0):
		i += g

	return i

inFile = open('flag.png_Crypted', 'rb').read()
for g in range(32, 512 + 32):
	for n in range(g):
		# tinh mask dua tren byte dau tien
		de = ord('\x89')
		mask_1 = ord(inFile[get_pos(0, n, g)]) ^ de
		mask_2 = ord(inFile[get_pos(0, -n, g)]) ^ de
		mask = (mask_1 & 0x0F) + (mask_2 & 0xF0)

		sign = ''
		for i in range(8):
			en_l = ord(inFile[get_pos(i, n, g)]) ^ mask
			en_h = ord(inFile[get_pos(i, -n, g)]) ^ mask
			de = (en_l & 0x0F) + (en_h & 0xF0)
			sign += chr(de)

		if ('\x89\x50\x4e\x47\x0d\x0a\x1a\x0a' == sign):
			print g, n, mask

Out nhận được là:

379 143 184

Viết hàm decrypt:

def decrypt(g, n, mask):
	inFile = open('flag.png_Crypted', 'rb')
	outFile = open('flag.png', 'wb')

	while (True):
		bytes = inFile.read(g)
		if len(bytes) == 0:
			break

		if len(bytes) < g:
			outFile.write(bytes)
		else:
			for i in range(g):
				try:
					en_l = ord(bytes[get_pos(i, n, g)]) ^ mask
					en_h = ord(bytes[get_pos(i, -n, g)]) ^ mask
					de = (en_l & 0x0F) + (en_h & 0xF0)
				except:
					print i
				outFile.write(chr(de))

	outFile.close()

Kết quả:

flag

ASIS_449e435e4c40dfa726f11b83a07b5471

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s