[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<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,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

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