CTF Writeups

Link

You registered on WordPress.com 3 years ago!

Thanks for flying with us. Keep up the good blogging!

Mới đó mà cũng đã được 3 năm, một cái blog với đủ các thứ linh tinh vụn vặt được nhét vào, tâm tư tình cảm học hành buồn chán đều có cả…

Mình xin thông báo là các bài viết liên quan đến CTF sẽ được chuyển sang địa chỉ mới này nhé. Rất có thể blog cũng sẽ được thay đổi địa chỉ, nhưng hiện giờ thì chưa :D

CTF Writeups: http://ctf.yeuchimse.com

[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

 

[Writeup] [ASIS CTF] Serial Number (Re75)

Standard

31-08-2013 23-57-31

File dự phòng: bin_serial

Nội dung chính

Mình mặc định là không làm về Re, nhưng vì bữa nay đội ngũ kỹ thuật nghỉ phép 02/09 gần hết, nên phải kiêm tạm. Tất nhiên nếu không bắt buộc thì mình cũng chẳng làm đâu emo_popo_shame

Xem thông tin:

bin_serial: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x869d2ca6cae1879c52484772089ac868e93fbef8, stripped

Chạy thử:

You should enter serial number in this form : XXXXXX-XXXXXX-XXXXXX
Enter serial number :

Xem danh sách string:

.rodata:0000000000401280   00000031 C \n\nYou should enter serial number in this form :
.rodata:00000000004012B1   00000017 C XXXXXX-XXXXXX-XXXXXX\n\n
.rodata:00000000004012C8   00000017 C Enter serial number :
.rodata:00000000004012DF   00000019 C Incorrect serial number.
.rodata:00000000004012F8   0000001D C \n\nIncorrect serial number.\n\n
.rodata:0000000000401318   0000001B C \nGood try. The flag is : \n
.eh_frame:00000000004013CF 00000006 C ;*3$\"

Phần kiểm tra key khá loằng ngoằng, nhưng cũng chỉ gồm những câu lệnh đơn giản:

.text:0000000000400C9B                 mov     ecx, [rbp-6Ch]  ; part_1
.text:0000000000400C9E                 mov     edx, 68DB8BADh
.text:0000000000400CA3                 mov     eax, ecx
.text:0000000000400CA5                 imul    edx
.text:0000000000400CA7                 sar     edx, 0Ch
.text:0000000000400CAA                 mov     eax, ecx
.text:0000000000400CAC                 sar     eax, 1Fh
.text:0000000000400CAF                 mov     edi, edx
.text:0000000000400CB1                 sub     edi, eax
.text:0000000000400CB3                 mov     esi, [rbp-6Ch]  ; part_1
.text:0000000000400CB6                 mov     edx, 68DB8BADh
.text:0000000000400CBB                 mov     eax, esi
.text:0000000000400CBD                 imul    edx
.text:0000000000400CBF                 sar     edx, 0Ch
.text:0000000000400CC2                 mov     eax, esi
.text:0000000000400CC4                 sar     eax, 1Fh
...
.text:0000000000400D89                 mov     eax, edx
.text:0000000000400D8B                 shl     eax, 2
.text:0000000000400D8E                 add     eax, edx
.text:0000000000400D90                 add     eax, eax
.text:0000000000400D92                 add     eax, [rbp-50h]
.text:0000000000400D95                 cmp     eax, 2B0ADh
.text:0000000000400D9A                 jz      short loc_400DB5
.text:0000000000400D9C                 mov     esi, offset aIncorrectSer_0 ; "\n\nIncorrect serial number.\n\n"
.text:0000000000400DA1                 mov     edi, offset _ZSt4cout ; std::cout
.text:0000000000400DA6                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc ; std::operator&lt;&lt;&lt;std::char_traits&lt;char&gt;&gt;(std::basic_ostream&lt;char,std::char_traits&lt;char&gt;&gt; &amp;,char  const*)
.text:0000000000400DAB                 mov     eax, 1
.text:0000000000400DB0                 jmp     loc_401118

Thử patch lệnh nhảy ở 0x400D9A, thấy in ra flag rác.

Viết lại thuật toán kiểm tra key và brute force (tất nhiên là không phải ai cũng brute được đâu emo_popo_look_down), tìm được 1 key hợp lệ:

958999-000000-979727

Kết quả:

Good try. The flag is : 
ASIS_f<i735<fh<gfi;ii:i;i4e:3hghdg;76

Hả  emo_popo_waaaht

Với vốn tiếng Anh khá đa dạng và nhiều màu sắc, hùng hổ lên IRC hỏi tụi admin ngay, là sao tôi tìm ra key rồi mà các ông lại không đưa flag? Các ông làm ăn cái kiểu gì đấy? Đây là chơi bời chứ có phải nghiêm túc gì đâu mà các ông như thế? Các ông nghĩ mình là ai?  emo_popo_rap

Mình tưởng tượng thôi =.= chứ thực ra thì lên viết nháp vài dòng tiếng Anh dựa theo ngữ pháp tiếng Việt, thằng admin1 nó kêu sang hỏi thằng admin2, vì nó không phụ trách mảng này. Lon ton sang hỏi thằng mới, thấy nó đang idle, chờ mãi không có reply.

Quay lại xem code, tìm hiểu coi phần in flag được thực hiện thế nào:

.text:0000000000400E12                 mov     esi, offset aGoodTry_TheFla ; "\nGood try. The flag is : \n"
.text:0000000000400E17                 mov     edi, offset _ZSt4cout ; std::cout
.text:0000000000400E1C                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char  const*)
.text:0000000000400E21                 mov     esi, 'A'
.text:0000000000400E26                 mov     edi, offset _ZSt4cout ; std::cout
.text:0000000000400E2B                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
.text:0000000000400E30                 mov     esi, 'S'
.text:0000000000400E35                 mov     rdi, rax
.text:0000000000400E38                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
.text:0000000000400E3D                 mov     esi, 'I'
.text:0000000000400E42                 mov     rdi, rax
.text:0000000000400E45                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
.text:0000000000400E4A                 mov     esi, 'S'
.text:0000000000400E4F                 mov     rdi, rax
.text:0000000000400E52                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
.text:0000000000400E57                 mov     esi, '_'
.text:0000000000400E5C                 mov     rdi, rax
.text:0000000000400E5F                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
.text:0000000000400E64                 mov     eax, [rbp-44h]
.text:0000000000400E67                 add     eax, 6          ; Add
.text:0000000000400E6A                 movsx   eax, al         ; Move with Sign-Extend
.text:0000000000400E6D                 mov     esi, eax
.text:0000000000400E6F                 mov     edi, offset _ZSt4cout ; std::cout
.text:0000000000400E74                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
.text:0000000000400E79                 mov     eax, [rbp-44h]
.text:0000000000400E7C                 sub     eax, 24h        ; Integer Subtraction
.text:0000000000400E7F                 movsx   eax, al         ; Move with Sign-Extend
.text:0000000000400E82                 mov     esi, eax
.text:0000000000400E84                 mov     edi, offset _ZSt4cout ; std::cout
.text:0000000000400E89                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
.text:0000000000400E8E                 mov     eax, [rbp-44h]
.text:0000000000400E91                 add     eax, 9          ; Add
.text:0000000000400E94                 movsx   eax, al         ; Move with Sign-Extend
.text:0000000000400E97                 mov     esi, eax
.text:0000000000400E99                 mov     edi, offset _ZSt4cout ; std::cout
.text:0000000000400E9E                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
.text:0000000000400EA3                 mov     eax, [rbp-44h]
.text:0000000000400EA6                 sub     eax, 29h        ; Integer Subtraction
.text:0000000000400EA9                 movsx   eax, al         ; Move with Sign-Extend
.text:0000000000400EAC                 mov     esi, eax
.text:0000000000400EAE                 mov     edi, offset _ZSt4cout ; std::cout
.text:0000000000400EB3                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
...
.text:00000000004010C5                 mov     eax, [rbp-44h]
.text:00000000004010C8                 sub     eax, 25h        ; Integer Subtraction
.text:00000000004010CB                 movsx   eax, al         ; Move with Sign-Extend
.text:00000000004010CE                 mov     esi, eax
.text:00000000004010D0                 mov     edi, offset _ZSt4cout ; std::cout
.text:00000000004010D5                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
.text:00000000004010DA                 mov     eax, [rbp-44h]
.text:00000000004010DD                 sub     eax, 29h        ; Integer Subtraction
.text:00000000004010E0                 movsx   eax, al         ; Move with Sign-Extend
.text:00000000004010E3                 mov     esi, eax
.text:00000000004010E5                 mov     edi, offset _ZSt4cout ; std::cout
.text:00000000004010EA                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
.text:00000000004010EF                 mov     eax, [rbp-44h]
.text:00000000004010F2                 sub     eax, 2Ah        ; Integer Subtraction
.text:00000000004010F5                 movsx   eax, al         ; Move with Sign-Extend
.text:00000000004010F8                 mov     esi, eax
.text:00000000004010FA                 mov     edi, offset _ZSt4cout ; std::cout
.text:00000000004010FF                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)
.text:0000000000401104                 mov     esi, offset asc_401333 ; "\n"
.text:0000000000401109                 mov     edi, offset _ZSt4cout ; std::cout
.text:000000000040110E                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char  const*)
.text:0000000000401113                 mov     eax, 0

Cũng cực kỳ dài, nhưng đại ý có thể thấy là nó in từng ký tự ra, bắt đầu bằng “ASIS_“.

Điểm đặc biệt là các ký tự tiếp theo đều được tính từ cùng một giá trị, nằm ở [rbp-44h], theo minh họa sau:

key = ''
key += chr((c + 0x06) & 0xFF)
key += chr((c - 0x24) & 0xFF)
key += chr((c + 0x09) & 0xFF)
key += chr((c - 0x29) & 0xFF)
key += chr((c - 0x2D) & 0xFF)
key += chr((c - 0x2B) & 0xFF)
key += chr((c - 0x24) & 0xFF)
key += chr((c + 0x06) & 0xFF)
key += chr((c + 0x08) & 0xFF)
key += chr((c - 0x24) & 0xFF)
key += chr((c + 0x07) & 0xFF)
key += chr((c + 0x06) & 0xFF)
key += chr((c + 0x09) & 0xFF)
key += chr((c - 0x25) & 0xFF)
key += chr((c + 0x09) & 0xFF)
key += chr((c + 0x09) & 0xFF)
key += chr((c - 0x26) & 0xFF)
key += chr((c + 0x09) & 0xFF)
key += chr((c - 0x25) & 0xFF)
key += chr((c + 0x09) & 0xFF)
key += chr((c - 0x2C) & 0xFF)
key += chr((c + 0x05) & 0xFF)
key += chr((c - 0x26) & 0xFF)
key += chr((c - 0x2D) & 0xFF)
key += chr((c + 0x08) & 0xFF)
key += chr((c + 0x07) & 0xFF)
key += chr((c + 0x08) & 0xFF)
key += chr((c + 0x04) & 0xFF)
key += chr((c + 0x07) & 0xFF)
key += chr((c - 0x25) & 0xFF)
key += chr((c - 0x29) & 0xFF)
key += chr((c - 0x2A) & 0xFF)

Trong đó c là một giá trị nào đó mà ta không biết, sẽ nằm ở [rbp-44h].

Nhưng tìm c rất đơn giản, vì ta đã biết định dạng của flag, nên đoạn code sau sẽ in ra những flag hợp lệ (có lẽ sẽ không quá nhiều):

def get_key():
	for c in range(255):
		key = ''
		key += chr((c + 0x06) & 0xFF)
		key += chr((c - 0x24) & 0xFF)
		key += chr((c + 0x09) & 0xFF)
		key += chr((c - 0x29) & 0xFF)
		key += chr((c - 0x2D) & 0xFF)
		key += chr((c - 0x2B) & 0xFF)
		key += chr((c - 0x24) & 0xFF)
		key += chr((c + 0x06) & 0xFF)
		key += chr((c + 0x08) & 0xFF)
		key += chr((c - 0x24) & 0xFF)
		key += chr((c + 0x07) & 0xFF)
		key += chr((c + 0x06) & 0xFF)
		key += chr((c + 0x09) & 0xFF)
		key += chr((c - 0x25) & 0xFF)
		key += chr((c + 0x09) & 0xFF)
		key += chr((c + 0x09) & 0xFF)
		key += chr((c - 0x26) & 0xFF)
		key += chr((c + 0x09) & 0xFF)
		key += chr((c - 0x25) & 0xFF)
		key += chr((c + 0x09) & 0xFF)
		key += chr((c - 0x2C) & 0xFF)
		key += chr((c + 0x05) & 0xFF)
		key += chr((c - 0x26) & 0xFF)
		key += chr((c - 0x2D) & 0xFF)
		key += chr((c + 0x08) & 0xFF)
		key += chr((c + 0x07) & 0xFF)
		key += chr((c + 0x08) & 0xFF)
		key += chr((c + 0x04) & 0xFF)
		key += chr((c + 0x07) & 0xFF)
		key += chr((c - 0x25) & 0xFF)
		key += chr((c - 0x29) & 0xFF)
		key += chr((c - 0x2A) & 0xFF)

		invalid = False
		for c in key:
			if (c not in '0123456789abcdef'):
				invalid = True
				break;

		if (not invalid):
			print key
			break

get_key()

Output nhận được là:

c9f4029ce9dcf8ff7f8f1b70edead843

Thành công ngoài mong đợi emo_popo_sure

Submit và Challenge solved. emo_popo_smile

[Writeup] [OverTheWire] [Natas] Level 17

Standard

Lời nói đầu

Nội dung chính

Kazam_screenshot_00000

Xem source:

<?

/*
CREATE TABLE `users` (
  `username` varchar(64) DEFAULT NULL,
  `password` varchar(64) DEFAULT NULL
);
*/

if(array_key_exists("username", $_REQUEST)) {
    $link = mysql_connect('localhost', 'natas17', '<censored>');
    mysql_select_db('natas17', $link);

    $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\"";
    if(array_key_exists("debug", $_GET)) {
        echo "Executing query: $query<br>";
    }

    $res = mysql_query($query, $link);
    if($res) {
    if(mysql_num_rows($res) > 0) {
        //echo "This user exists.<br>";
    } else {
        //echo "This user doesn't exist.<br>";
    }
    } else {
        //echo "Error in query.<br>";
    }

    mysql_close($link);
} else {
?>

<form action="index.php" method="POST">
Username: <input name="username"><br>
<input type="submit" value="Check existence" />
</form>
<? } ?>

Tất cả các thông báo đều đã bị xoẹt xoẹt, làm sao đây emo_popo_cry

Dựa vào cái gì để phân biệt giữa True và False bây giờ emo_popo_pudency Continue reading

[Writeup] [OverTheWire] [Natas] Level 16

Standard

Lời nói đầu

  • [Writeup] [OverTheWire] [Natas] Level 14, Level 15
  • Độ khó của bạn Natas này là basic (giống như bạn ấy tự giới thiệu). Nhưng với mình thì chẳng hề… khó chút nào emo_popo_beat_brick j/k
  • Mình hiện đang song song hoạt động ở blog này và http://forum.botbie.com/forum.php (mới mở). Sau này nếu bên đó ổn định thì cũng khó nói, nên tốt nhất các bạn cứ follow cả hai trang :”>

Nội dung chính

Screenshot 2013-08-22 11:20:16

Xem source:

<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
    $key = $_REQUEST["needle"];
}

if($key != "") {
    if(preg_match('/[;|&`\'"]/',$key)) {
        print "Input contains an illegal character!";
    } else {
        passthru("grep -i \"$key\" dictionary.txt");
    }
}
?>

Thấy quen quen emo_popo_shame Continue reading

[Writeup] [OverTheWire] [Natas] Level 14, Level 15

Standard

Lời nói đầu

  • [Writeup] [OverTheWire] [Natas] Level 12, Level 13
  • Độ khó của bạn Natas này là basic (giống như bạn ấy tự giới thiệu). Nhưng với mình thì chẳng hề… khó chút nào emo_popo_beat_brick j/k
  • Mình hiện đang song song hoạt động ở blog này và http://forum.botbie.com/forum.php (mới mở). Sau này nếu bên đó ổn định thì cũng khó nói, nên tốt nhất các bạn cứ follow cả hai trang :”>

Level 14

18-08-2013 16-39-37

Xem source:

<?
if(array_key_exists("username", $_REQUEST)) {
    $link = mysql_connect('localhost', 'natas14', '<censored>');
    mysql_select_db('natas14', $link);

    $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\" and password=\"".$_REQUEST["password"]."\"";
    if(array_key_exists("debug", $_GET)) {
        echo "Executing query: $query<br>";
    }

    if(mysql_num_rows(mysql_query($query, $link)) > 0) {
            echo "Successful login! The password for natas15 is <censored><br>";
    } else {
            echo "Access denied!<br>";
    }
    mysql_close($link);
} else {
?>

Ta thấy ngay được là username và password đều không bị escape. Inject với câu lệnh được dạy trong sách giáo khoa:

username = " OR 1=1#
password = <gì cũng được>

Kết quả:

Successful login! The password for natas15 is AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J

natas15:AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J

Tất nhiên đây chỉ là task để cảnh báo rằng đã đến phần của SQLi, và chúng ta nên chuẩn bị sẵn tâm lý cho những level phức tạp hơn về sau, thay vì hạnh phúc với thành quá vừa thu được. Continue reading

[Writeup] [OverTheWire] [Natas] Level 12, Level 13

Standard

Lời nói đầu

  • [Writeup] [OverTheWire] [Natas] Level 11
  • Độ khó của bạn Natas này là basic (giống như bạn ấy tự giới thiệu). Nhưng với mình thì chẳng hề… khó chút nào emo_popo_beat_brick j/k
  • Mình hiện đang song song hoạt động ở blog này và http://forum.botbie.com/forum.php (mới mở). Sau này nếu bên đó ổn định thì cũng khó nói, nên tốt nhất các bạn cứ follow cả hai trang :”>

Level 12

18-08-2013 05-42-51

Xem source:

<?

function genRandomString() {
    $length = 10;
    $characters = "0123456789abcdefghijklmnopqrstuvwxyz";
    $string = "";

    for ($p = 0; $p < $length; $p++) {
        $string .= $characters[mt_rand(0, strlen($characters)-1)];
    }

    return $string;
}

function makeRandomPath($dir, $ext) {
    do {
    $path = $dir."/".genRandomString().".".$ext;
    } while(file_exists($path));
    return $path;
}

function makeRandomPathFromFilename($dir, $fn) {
    $ext = pathinfo($fn, PATHINFO_EXTENSION);
    return makeRandomPath($dir, $ext);
}

if(array_key_exists("filename", $_POST)) {
    $target_path = makeRandomPathFromFilename("upload", $_POST["filename"]);

        if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) {
        echo "File is too big";
    } else {
        if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
            echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded";
        } else{
            echo "There was an error uploading the file, please try again!";
        }
    }
} else {
?>

<form enctype="multipart/form-data" action="index.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="1000" />
<input type="hidden" name="filename" value="<? print genRandomString(); ?>.jpg" />
Choose a JPEG to upload (max 1KB):<br/>
<input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>

Continue reading