hudak
This Challenge is one of my interesting RE probs what the idea was quiet awesome!
- Static Analysis
Given prob is x86 stripped elf binary.
1 2 | zero@ubuntu:~/Desktop$ file hudak hudak: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter stripped | cs |
let's open with IDA!
First, we can see password check routine and get string from stdin.
1 2 3 4 5 6 7 8 9 10 11 | // - main func __printf_chk(1, "Enter the password.\n"); get_string(0, &buffer, 80, 10); if ( strlen(&buffer) == 30 ) { .... } // - get_string func ... *(buffer - 1) = 0xFFu; ... | cs |
As we could see, buffer size is 80 bytes and data is scanned with get_string (using read() internally) func filling last byte with 0xff.
And checking if buffer's length is 30 bytes ( actually 29 bytes because of 0xff )
After comparing length with 30(29), 0x080489F0 func which is calling another func and compares processed final data with hard-coded data by using memcmp() is called.
Hard-corded is 32 bytes length data. like below.
1 2 | 04 19 19 68 43 41 5B 04 C8 44 43 43 43 40 45 47 68 68 06 5A 52 56 03 56 44 03 5E 06 68 19 00 00 | cs |
0x08048690 func :
I think that this function just returns index of array ( or pointer ). It means useless
0x8048900 func :
This function works as rotating 1 byte to left 30 times like below
1 2 3 4 5 6 7 8 9 10 | // - 0x8048770 func if ( len > 0 ) // rotate { i = 0; do { arr[i] = *(buf + (v7 + i) % len); ++i; } while ( len > i ); | cs |
1 2 3 4 5 6 7 8 9 10 | // Result of 0x8048900 func // i'll set \xff as - for convience input[0] = abcdefghijklmnopqrstuvwxyz012- input[1] = bcdefghijklmnopqrstuvwxyz012-a input[2] = cdefghijklmnopqrstuvwxyz012-ab ... input[26] = 012-abcdefghijklmnopqrstuvwxyz input[27] = 12-abcdefghijklmnopqrstuvwxyz0 input[28] = 2-abcdefghijklmnopqrstuvwxyz01 input[29] = -abcdefghijklmnopqrstuvwxyz012 | cs |
0x8048810 func :
This is the most important function! This function does bubble-sort whole list ( input )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // - 0x8048810 func do { if ( v10 > 0 ) { v7 = 0; do { v8 = v5[v7 + 1]; v9 = v5[v7]; if ( memcmp(v5[v7], v5[v7 + 1], v11) > 0 ) { v5[v7] = v8; v5[v7 + 1] = v9; } ++v7; } while ( v7 != v10 ); } ++v12; } while ( v11 > v12 ); | cs |
1 2 3 4 5 6 7 8 9 | // -> Result of 0x4048810 input[26] = 012-abcdefghijklmnopqrstuvwxyz input[27] = 12-abcdefghijklmnopqrstuvwxyz0 input[28] = 2-abcdefghijklmnopqrstuvwxyz01 input[0] = abcdefghijklmnopqrstuvwxyz012- input[1] = bcdefghijklmnopqrstuvwxyz012-a input[2] = cdefghijklmnopqrstuvwxyz012-ab ... input[29] = -abcdefghijklmnopqrstuvwxyz012 | cs |
0x80486E0 func :
Extract last byte of 'processed data' ( above data ) and xor with 0x37.
1 2 3 4 5 6 7 | // - 0x80486e0 func do { result[v8 - 1] = *(*(v4 + 4 * v8 - 4) + v6) ^ 0x37; ++v8; } while ( v8 != v7 ); | cs |
Back to 0x80489f0 function, xored data is compared with hard-coded data what i mentioned above.
1 2 | // - 0x80489f0 func return memcmp(&table, v5, 31u) == 0; | cs |
Of course, if 'memcpy(...) == 0' is true, we can see "congrat" message on screen.
Now all we have to do is xor hard-coded with 0x37 ( because xor can be reversible )
let's write following C program.
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> unsigned char table[32] = { 0x04, 0x19, 0x19, 0x68, 0x43, 0x41, 0x5B, 0x04, 0xC8, 0x44, 0x43, 0x43, 0x43, 0x40, 0x45, 0x47, 0x68, 0x68, 0x06, 0x5A, 0x52, 0x56, 0x03, 0x56, 0x44, 0x03, 0x5E, 0x06, 0x68, 0x19, 0x00, 0x00 }; void main() { for (int i = 0; i < 32; (i % 16 != 15) ? printf("%#x ", table[i] ^ 0x37) : printf("%#x\n", table[i] ^ 0x37), ++i); } | cs |
1 2 3 4 5 6 | // - Hex Result 0x33 0x2e 0x2e 0x5f 0x74 0x76 0x6c 0x33 0xff 0x73 0x74 0x74 0x74 0x77 0x72 0x70 0x5f 0x5f 0x31 0x6d 0x65 0x61 0x34 0x61 0x73 0x34 0x69 0x31 0x5f 0x2e 0x37 0x37 // - String ( 0xff ->'-' ) 3.._tvl3-stttwrp__1mea4as4i1_.77 | cs |
So, The result data will be the last byte of each lists.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ???????????????????????????????3 ???????????????????????????????. ???????????????????????????????. ???????????????????????????????_ ???????????????????????????????t ???????????????????????????????v ???????????????????????????????l ???????????????????????????????3 ???????????????????????????????- ???????????????????????????????s ???????????????????????????????t ???????????????????????????????t ???????????????????????????????t ???????????????????????????????w ???????????????????????????????r ???????????????????????????????p ???????????????????????????????_ ???????????????????????????????_ ???????????????????????????????1 ???????????????????????????????m ???????????????????????????????e ???????????????????????????????a ???????????????????????????????4 ???????????????????????????????a ???????????????????????????????s ???????????????????????????????4 ???????????????????????????????i ???????????????????????????????1 ???????????????????????????????_ ???????????????????????????????. | cs |
As we think about it, we can guess first byte of each lists. Because whole lists are bubble-sorted.
Then straight line of 'first bytes' is sorted! So ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | .??????????????????????????????3 .??????????????????????????????. .??????????????????????????????. 1??????????????????????????????_ 1??????????????????????????????t 3??????????????????????????????v 3??????????????????????????????l 4??????????????????????????????3 5??????????????????????????????- _??????????????????????????????s _??????????????????????????????t _??????????????????????????????t _??????????????????????????????t a??????????????????????????????w a??????????????????????????????r e??????????????????????????????p i??????????????????????????????_ l??????????????????????????????_ m??????????????????????????????1 p??????????????????????????????m r??????????????????????????????e s??????????????????????????????a s??????????????????????????????4 t??????????????????????????????a t??????????????????????????????s t??????????????????????????????4 t??????????????????????????????i v??????????????????????????????1 w??????????????????????????????_ -??????????????????????????????. | cs |
And we can also guess the flag's first 2 bytes because each list will rotate and rotate then someday that 2 chars will stick together.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 3. .. .. _1 t1 v3 l3 34 -5 s_ t_ wa ra pe _i _l 1m mp er as 4s at st 4t it 1v _w .- | cs |
But there are a lot of cases to guess. We need to narrow down the cases.
I think that 30 byte ( include 0xff ) is the final flag then it could be readable.
It means it doesn't start with bytes like '0xff', '.', '_' and ends with 0xff. There is one case which ends with 0xff -> '.-'
With these clues i narrow down the cases like below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | t1 v3 l3 34 wa ra pe 1m mp er as 4s at st 4t it 1v | cs |
First 2 bytes would be on that list and last byte is '.'.
With more search, we can guess string with string segment like below.
"??????????????????????????...", last byte is '.' but there are 2 segs '..' and '3.'. I think Using '3.' is improper to make flag than '..'.
"_was_", there are string segments ( _w , wa, as, st or s_ ). start and end with 'w' is only _w, wa.
I just made 3 chars groups in list like 'was', '...' by following process. Then connect them one by one.
With Following process, i can reach the answer like below.
1 2 3 4 5 6 7 8 9 | ??????????????????????????... _was_ _it_was_ 1mperat1v3... ????????_it_was_1mperat1v3... ??????st_it_was_1mperat1v3... // cannot be 'at' ????34st_it_was_1mperat1v3... // cannot be 'as' 4t_l34st_it_was_1mperat1v3... // already 'at' is used | cs |
So the flag is 4t_l34st_it_was_1mperat1v3...
Let's check it out!
1 2 3 4 | zero@ubuntu:~/Desktop$ ./hudak Enter the password. 4t_l34st_it_was_1mperat1v3... Congratulations! :) | cs |
'CTFs > Plaid 2014' 카테고리의 다른 글
[Plaid 2014] pwnable : kappa (0) | 2016.08.27 |
---|---|
[Plaid 2014] pwnable : ezhp (0) | 2016.08.27 |
[Plaid 2014] forensic : zfs (0) | 2016.08.27 |
[Plaid 2014] forensic : rsa (0) | 2016.08.27 |
[Plaid 2014] forensic : curlcore (0) | 2016.08.27 |