{"id":13057,"date":"2016-06-25T13:22:34","date_gmt":"2016-06-25T11:22:34","guid":{"rendered":"http:\/\/www.codilime.com\/?p=13057"},"modified":"2016-12-01T23:19:22","modified_gmt":"2016-12-01T22:19:22","slug":"whitehat11-re1","status":"publish","type":"post","link":"https:\/\/codisec.com\/whitehat11-re1\/","title":{"rendered":"Whitehat11 RE1"},"content":{"rendered":"
Link: https:\/\/wargame.whitehat.vn\/Challenges\/DetailContest\/141<\/a> http:\/\/material.wargame.whitehat.vn\/contests\/11\/re1_d3309936b177b41dada3796c4c3acadf.zip<\/a><\/p><\/blockquote>\n see below<\/a><\/p>\n When executed the program asks for input. It seems that regardless of what is being provided the answer is always “wrong<\/em>“.<\/p>\n Simplified<\/strong> reversed C code for the program’s main function looks like the following:<\/p>\n The program consists of two processes. The parent prints replies based on the child’s response. Both processes are (at least theoretically) protected against It can clearly be seen that the only answer that is not “wrong<\/em>” is being printed when the child process responds with a nonzero integer.<\/p>\n On the other hand, the child process calls either By looking at the following code:<\/p>\n it can be seen that the only path that results in a correct response is if the input:<\/p>\n Simplified<\/strong> reversed C code for the This function:<\/p>\n By looking at the following code:<\/p>\n it can be seen that the mangling is actually:<\/p>\n Link: https:\/\/wargame.whitehat.vn\/Challenges\/DetailContest\/141 Points: 100 Category: RE Description http:\/\/material.wargame.whitehat.vn\/contests\/11\/re1_d3309936b177b41dada3796c4c3acadf.zip tl;dr see below Solving the task When executed the program asks for input. It seems that regardless of what is being provided the answer is always “wrong“. Simplified reversed C code for…<\/span> <\/p>\n <\/a><\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[13],"tags":[10],"yoast_head":"\n\n\n\n\n\n\n\n\n\n\n\n\t\n
\nPoints: 100
\nCategory: RE<\/p>\nDescription<\/h2>\n
tl;dr<\/h2>\n
Solving the task<\/h2>\n
int __cdecl __noreturn main(int, const char**, const char**)\r\n{\r\n const bool bCheckPtrace = detectDebugging();\r\n\r\n if ( pipe(pipe_1) == -1 )\r\n exit(1);\r\n if ( pipe(pipe_2) == -1 )\r\n exit(1);\r\n\r\n const __pid_t pid = fork();\r\n if ( pid != -1 ) {\r\n\r\n if ( pid )\r\n {\r\n ssize_t numReada;\r\n char bufRead[200];\r\n char bufWrite[200];\r\n\r\n close(pipe_1[0]);\r\n close(pipe_2[1]);\r\n\r\n while ( 1 )\r\n {\r\n puts(\"Input key : \");\r\n memset(bufWrite, 0, 200);\r\n gets(bufWrite, 0);\r\n if (write(pipe_1[1], bufWrite, strlen(bufWrite)) != strlen(bufWrite)) {\r\n puts(\"parent - partial\/failed write\");\r\n }\r\n do\r\n {\r\n memset(bufRead, 0, 200);\r\n numReada = read(pipe_2[0], bufRead, 200);\r\n if (bCheckPtrace || checkDebuggerProcessRunning())\r\n {\r\n puts(\"Wrong !!!\\n\");\r\n }\r\n else if ( !checkStringIsNumber(bufRead) )\r\n {\r\n puts(\"Wrong !!!\\n\");\r\n }\r\n else\r\n {\r\n if ( atoi(bufRead) )\r\n {\r\n puts(\"True\");\r\n if ( close(pipe_1[1]) == -1 )\r\n exit(1);\r\n exit(0);\r\n }\r\n puts(\"Wrong !!!\\n\");\r\n }\r\n }\r\n while ( numReada == -1 );\r\n }\r\n }\r\n\r\n char user_input[200];\r\n ssize_t numRead;\r\n\r\n close(pipe_1[1]);\r\n close(pipe_2[0]);\r\n\r\n while ( 1 )\r\n {\r\n memset(user_input, 0, 200);\r\n numRead = read(pipe_1[0], user_input, 200);\r\n if ( numRead == -1 )\r\n break;\r\n if ( numRead )\r\n {\r\n if ( childCheckDebugResult() )\r\n {\r\n responseFalse();\r\n }\r\n else if ( user_input[0] == '{' )\r\n {\r\n if ( strlen(user_input) == 42 )\r\n {\r\n if ( !strncmp(&user_input[1], \"5 xxxxxx 1\", 10) )\r\n {\r\n if ( user_input[strlen(user_input) - 1] == '}' )\r\n {\r\n if ( !strncmp(&user_input[31], \"4 xxxxxx d\", 10) )\r\n {\r\n if ( !confuseKey(user_input, 42) )\r\n {\r\n responseFalse();\r\n }\r\n else if ( !strncmp(user_input, \"{da xxxxxxxxxxxx CENSORED xxxxxxxxxxxx 8c}\", 42) )\r\n {\r\n responseTrue();\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n }\r\n exit(1);\r\n\r\n }\r\n exit(1);\r\n}<\/pre>\n
ptrace<\/code>. It could be possible to still debug both, but in this case it won’t be necessary.<\/p>\n
if ( atoi(bufRead) )\r\n{\r\n puts(\"True\");\r\n if ( close(pipe_1[1]) == -1 )\r\n exit(1);\r\n exit(0);\r\n}<\/pre>\n
responseFalse<\/code> or
responseTrue<\/code> functions, which in turn respond to the parent with
\"0\"<\/code> and
\"1\"<\/code> respectively.<\/p>\n
else if ( user_input[0] == '{' )\r\n{\r\n if ( strlen(user_input) == 42 )\r\n {\r\n if ( !strncmp(&user_input[1], \"5 xxxxxx 1\", 10) )\r\n {\r\n if ( user_input[strlen(user_input) - 1] == '}' )\r\n {\r\n if ( !strncmp(&user_input[31], \"4 xxxxxx d\", 10) )\r\n {\r\n if ( !confuseKey(user_input, 42) )\r\n {\r\n responseFalse();\r\n }\r\n else if ( !strncmp(user_input, \"{da xxxxxxxxxxxx CENSORED xxxxxxxxxxxx 8c}\", 42) )\r\n {\r\n responseTrue();<\/pre>\n
\n
\"{5 xxxxxx 1\"<\/code>,<\/li>\n
\"4 xxxxxx d}\"<\/code>,<\/li>\n
confuseKey<\/code> is nonzero<\/li>\n
\"{da xxxxxxxxxxxx CENSORED xxxxxxxxxxxx 8c}\"<\/code>.<\/li>\n<\/ul>\n
confuseKey<\/code> function looks like the following:<\/p>\n
signed __int64 __fastcall confuseKey(char *user_input, int _42)\r\n{\r\n char szPart1[15]\r\n char szPart2[15];\r\n char szPart3[15];\r\n char szPart4[15];\r\n\r\n *(_QWORD *)szPart1 = 0LL;\r\n *(_DWORD *)&szPart1[8] = 0;\r\n *(_WORD *)&szPart1[12] = 0;\r\n szPart1[14] = 0;\r\n *(_QWORD *)szPart2 = 0LL;\r\n *(_DWORD *)&szPart2[8] = 0;\r\n *(_WORD *)&szPart2[12] = 0;\r\n szPart2[14] = 0;\r\n *(_QWORD *)szPart3 = 0LL;\r\n *(_DWORD *)&szPart3[8] = 0;\r\n *(_WORD *)&szPart3[12] = 0;\r\n szPart3[14] = 0;\r\n *(_QWORD *)szPart4 = 0LL;\r\n *(_DWORD *)&szPart4[8] = 0;\r\n *(_WORD *)&szPart4[12] = 0;\r\n szPart4[14] = 0;\r\n\r\n if ( _42 == 42 )\r\n {\r\n if ( user_input )\r\n {\r\n if ( strlen(user_input) == 42 )\r\n {\r\n if ( user_input[0] == '{' )\r\n {\r\n strncpy(szPart1, user_input + 1, 10);\r\n strncpy(szPart2, user_input + 11, 10);\r\n strncpy(szPart3, user_input + 21, 10);\r\n strncpy(szPart4, user_input + 31, 10);\r\n memset(user_input, 0, _42);\r\n user_input[0] = '{';\r\n strcat(user_input, szPart3);\r\n strcat(user_input, szPart4);\r\n strcat(user_input, szPart1);\r\n strcat(user_input, szPart2);\r\n user_input[41] = '}';\r\n return 1;\r\n }\r\n else\r\n {\r\n return 0;\r\n }\r\n }\r\n else\r\n {\r\n return 0;\r\n }\r\n }\r\n else\r\n {\r\n return 0;\r\n }\r\n }\r\n else\r\n {\r\n return 0;\r\n }\r\n}<\/pre>\n
\n
strncpy(szPart1, user_input + 1, 10);\r\nstrncpy(szPart2, user_input + 11, 10);\r\nstrncpy(szPart3, user_input + 21, 10);\r\nstrncpy(szPart4, user_input + 31, 10);\r\nmemset(user_input, 0, _42);\r\nuser_input[0] = '{';\r\nstrcat(user_input, szPart3);\r\nstrcat(user_input, szPart4);\r\nstrcat(user_input, szPart1);\r\nstrcat(user_input, szPart2);\r\nuser_input[41] = '}';\r\nreturn 1;<\/pre>\n
\n
'{'<\/code> and
'}'<\/code>,<\/li>\n
'{'<\/code> and
'}'<\/code>.<\/li>\n<\/ul>\n
The solution<\/h2>\n
{ | dxxxxxxxx3 | 4xxxxxxxxd | 5xxxxxxxx1 | 0xxxxxxxxc | }\r\n | | | |\r\n ^ | ^ | \/ ^ \/ ^\r\n | | | | \/ | \/ |\r\n \\_____________________\/ | \/ \/\r\n | \\______________________\/ \/\r\n \\_______________________\/ \/\r\n \\____________________\/<\/pre>\n
The program<\/h2>\n
__int64 __cdecl responseFalse()\r\n{\r\n return write(pipe_2[1], \"0\", 1) == 1;\r\n}\r\n\r\n\r\n__int64 __cdecl responseTrue()\r\n{\r\n return write(pipe_2[1], \"1\", 1) == 1;\r\n}\r\n\r\n\r\nsigned __int64 __fastcall confuseKey(char *user_input, int _42)\r\n{\r\n char szPart1[15]\r\n char szPart2[15];\r\n char szPart3[15];\r\n char szPart4[15];\r\n\r\n *(_QWORD *)szPart1 = 0LL;\r\n *(_DWORD *)&szPart1[8] = 0;\r\n *(_WORD *)&szPart1[12] = 0;\r\n szPart1[14] = 0;\r\n *(_QWORD *)szPart2 = 0LL;\r\n *(_DWORD *)&szPart2[8] = 0;\r\n *(_WORD *)&szPart2[12] = 0;\r\n szPart2[14] = 0;\r\n *(_QWORD *)szPart3 = 0LL;\r\n *(_DWORD *)&szPart3[8] = 0;\r\n *(_WORD *)&szPart3[12] = 0;\r\n szPart3[14] = 0;\r\n *(_QWORD *)szPart4 = 0LL;\r\n *(_DWORD *)&szPart4[8] = 0;\r\n *(_WORD *)&szPart4[12] = 0;\r\n szPart4[14] = 0;\r\n\r\n if ( _42 == 42 )\r\n {\r\n if ( user_input )\r\n {\r\n if ( strlen(user_input) == 42 )\r\n {\r\n if ( user_input[0] == '{' )\r\n {\r\n strncpy(szPart1, user_input + 1, 10);\r\n strncpy(szPart2, user_input + 11, 10);\r\n strncpy(szPart3, user_input + 21, 10);\r\n strncpy(szPart4, user_input + 31, 10);\r\n memset(user_input, 0, _42);\r\n user_input[0] = '{';\r\n strcat(user_input, szPart3);\r\n strcat(user_input, szPart4);\r\n strcat(user_input, szPart1);\r\n strcat(user_input, szPart2);\r\n user_input[41] = '}';\r\n return 1;\r\n }\r\n else\r\n {\r\n return 0;\r\n }\r\n }\r\n else\r\n {\r\n return 0;\r\n }\r\n }\r\n else\r\n {\r\n return 0;\r\n }\r\n }\r\n else\r\n {\r\n return 0;\r\n }\r\n}\r\n\r\n\r\nint __cdecl __noreturn main(int, const char**, const char**)\r\n{\r\n const bool bCheckPtrace = detectDebugging();\r\n\r\n if ( pipe(pipe_1) == -1 )\r\n exit(1);\r\n if ( pipe(pipe_2) == -1 )\r\n exit(1);\r\n\r\n const __pid_t pid = fork();\r\n if ( pid != -1 ) {\r\n\r\n if ( pid )\r\n {\r\n ssize_t numReada;\r\n char bufRead[200];\r\n char bufWrite[200];\r\n\r\n close(pipe_1[0]);\r\n close(pipe_2[1]);\r\n\r\n while ( 1 )\r\n {\r\n puts(\"Input key : \");\r\n memset(bufWrite, 0, 200);\r\n gets(bufWrite, 0);\r\n if (write(pipe_1[1], bufWrite, strlen(bufWrite)) != strlen(bufWrite)) {\r\n puts(\"parent - partial\/failed write\");\r\n }\r\n do\r\n {\r\n memset(bufRead, 0, 200);\r\n numReada = read(pipe_2[0], bufRead, 200);\r\n if (bCheckPtrace || checkDebuggerProcessRunning())\r\n {\r\n puts(\"Wrong !!!\\n\");\r\n }\r\n else if ( !checkStringIsNumber(bufRead) )\r\n {\r\n puts(\"Wrong !!!\\n\");\r\n }\r\n else\r\n {\r\n if ( atoi(bufRead) )\r\n {\r\n puts(\"True\");\r\n if ( close(pipe_1[1]) == -1 )\r\n exit(1);\r\n exit(0);\r\n }\r\n puts(\"Wrong !!!\\n\");\r\n }\r\n }\r\n while ( numReada == -1 );\r\n }\r\n }\r\n\r\n char user_input[200];\r\n ssize_t numRead;\r\n\r\n close(pipe_1[1]);\r\n close(pipe_2[0]);\r\n\r\n while ( 1 )\r\n {\r\n memset(user_input, 0, 200);\r\n numRead = read(pipe_1[0], user_input, 200);\r\n if ( numRead == -1 )\r\n break;\r\n if ( numRead )\r\n {\r\n if ( childCheckDebugResult() )\r\n {\r\n responseFalse();\r\n }\r\n else if ( user_input[0] == '{' )\r\n {\r\n if ( strlen(user_input) == 42 )\r\n {\r\n if ( !strncmp(&user_input[1], \"5 xxxxxx 1\", 10) )\r\n {\r\n if ( user_input[strlen(user_input) - 1] == '}' )\r\n {\r\n if ( !strncmp(&user_input[31], \"4 xxxxxx d\", 10) )\r\n {\r\n if ( !confuseKey(user_input, 42) )\r\n {\r\n responseFalse();\r\n }\r\n else if ( !strncmp(user_input, \"{da xxxxxxxxxxxx CENSORED xxxxxxxxxxxx 8c}\", 42) )\r\n {\r\n responseTrue();\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n else\r\n {\r\n responseFalse();\r\n }\r\n }\r\n }\r\n exit(1);\r\n\r\n }\r\n exit(1);\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"