Skip to content

ebCTF bin300 write up

In this post I will cover the third binary challenge of the Eindbazen CTF located at

This binary challenge is based on a x86-64 elf file which prompts for a password: $ file ./moon
moon: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=fd80fd39006c069a230b2442b8072586f5386d28, not stripped $ $ ./moon 
Enter your password: asd

Examining the external libraries with ldd, It can be seen that this program uses libld to load external libraries. $ ldd moon (0x00007fffa89dc000) => /lib64/ (0x00007fade429a000) => /lib64/ (0x00007fade4096000) => /lib64/ (0x00007fade3cee000)
	/lib64/ (0x00007fade4590000)

By using nm, large list of lua function calls are shown. This lead to the conclusion that probably this binary has embedded a Lua interpreter. $ nm moon | grep lua | wc -l
292 $ $ nm moon | grep lua | head -10
000000000040b540 t f_luaopen
00000000004021cc T load_challenge_lua
00000000004024d0 T luaA_pushobject
00000000004152f0 t luaB_assert
0000000000415080 t luaB_auxwrap
00000000004140c0 t luaB_cocreate
0000000000414d30 t luaB_collectgarbage
0000000000415120 t luaB_coresume
00000000004140a0 t luaB_corunning
0000000000415010 t luaB_costatus $ 

The main() function of the program shows calls to the Lua interfaces luaL_newstate, luaL_openlibs and lua_close. Also, a suspicious function call to load_challenge_lua is performed. $ gdb -q ./moon 
Reading symbols from /home/user/ohm2013/ebCTF/bin/bin300/moon...(no debugging symbols found)...done.
gdb-peda$ pdisass  main
Dump of assembler code for function main:
   0x000000000040227f <+0>:	push   rbp
   0x0000000000402280 <+1>:	mov    rbp,rsp
   0x0000000000402283 <+4>:	sub    rsp,0x20
   0x0000000000402287 <+8>:	mov    DWORD PTR [rbp-0x14],edi
   0x000000000040228a <+11>:	mov    QWORD PTR [rbp-0x20],rsi
   0x000000000040228e <+15>:	call   0x411170 
   0x0000000000402293 <+20>:	mov    QWORD PTR [rbp-0x8],rax
   0x0000000000402297 <+24>:	mov    rax,QWORD PTR [rbp-0x8]
   0x000000000040229b <+28>:	mov    rdi,rax
   0x000000000040229e <+31>:	mov    eax,0x0
   0x00000000004022a3 <+36>:	call   0x4111a0 
   0x00000000004022a8 <+41>:	mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004022ac <+45>:	mov    rdi,rax
   0x00000000004022af <+48>:	call   0x4021cc 
   0x00000000004022b4 <+53>:	mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004022b8 <+57>:	mov    rdi,rax
   0x00000000004022bb <+60>:	call   0x40b970 
   0x00000000004022c0 <+65>:	mov    eax,0x0
   0x00000000004022c5 <+70>:	leave  
   0x00000000004022c6 <+71>:	ret    
End of assembler dump.

Closing the scope to the function load_challenge_lua, It also calls to luaL_loadbuffer at 0x000000000040224e

gdb-peda$ pdisass load_challenge_lua
Dump of assembler code for function load_challenge_lua:
   0x00000000004021cc <+0>:	push   rbp
   0x00000000004021cd <+1>:	mov    rbp,rsp
   0x00000000004021d0 <+4>:	sub    rsp,0x20
   0x00000000004021d4 <+8>:	mov    QWORD PTR [rbp-0x18],rdi
   0x00000000004021d8 <+12>:	mov    DWORD PTR [rbp-0xc],0x56
   0x00000000004021df <+19>:	mov    DWORD PTR [rbp-0x4],0xec
   0x00000000004021e6 <+26>:	jmp    0x40222b 
   0x00000000004021e8 <+28>:	mov    eax,DWORD PTR [rip+0x22535e]        # 0x62754c 
   0x00000000004021ee <+34>:	mov    edx,eax
   0x00000000004021f0 <+36>:	movsxd rcx,edx
   0x00000000004021f3 <+39>:	movzx  ecx,BYTE PTR [rcx+0x627340]
   0x00000000004021fa <+46>:	mov    edi,ecx
   0x00000000004021fc <+48>:	mov    ecx,DWORD PTR [rbp-0xc]
   0x00000000004021ff <+51>:	mov    esi,ecx
   0x0000000000402201 <+53>:	sar    esi,0x1f
   0x0000000000402204 <+56>:	shr    esi,0x18
   0x0000000000402207 <+59>:	add    ecx,esi
   0x0000000000402209 <+61>:	and    ecx,0xff
   0x000000000040220f <+67>:	sub    ecx,esi
   0x0000000000402211 <+69>:	xor    ecx,edi
   0x0000000000402213 <+71>:	movsxd rdx,edx
   0x0000000000402216 <+74>:	mov    BYTE PTR [rdx+0x627340],cl
   0x000000000040221c <+80>:	add    eax,0x1
   0x000000000040221f <+83>:	mov    DWORD PTR [rip+0x225327],eax        # 0x62754c 
   0x0000000000402225 <+89>:	mov    eax,DWORD PTR [rbp-0x4]
   0x0000000000402228 <+92>:	add    DWORD PTR [rbp-0xc],eax
   0x000000000040222b <+95>:	mov    eax,DWORD PTR [rip+0x22531b]        # 0x62754c 
   0x0000000000402231 <+101>:	cmp    eax,0x1e6
   0x0000000000402236 <+106>:	jle    0x4021e8 
   0x0000000000402238 <+108>:	mov    rax,QWORD PTR [rbp-0x18]
   0x000000000040223c <+112>:	mov    ecx,0x41c7e4
   0x0000000000402241 <+117>:	mov    edx,0x1e7
   0x0000000000402246 <+122>:	mov    esi,0x627340
   0x000000000040224b <+127>:	mov    rdi,rax
   0x000000000040224e <+130>:	call   0x411110 
   0x0000000000402253 <+135>:	mov    DWORD PTR [rbp-0x8],eax
   0x0000000000402256 <+138>:	cmp    DWORD PTR [rbp-0x8],0x0
   0x000000000040225a <+142>:	jne    0x40227a 
   0x000000000040225c <+144>:	mov    rax,QWORD PTR [rbp-0x18]
   0x0000000000402260 <+148>:	mov    ecx,0x0
   0x0000000000402265 <+153>:	mov    edx,0x0
   0x000000000040226a <+158>:	mov    esi,0x0
   0x000000000040226f <+163>:	mov    rdi,rax
   0x0000000000402272 <+166>:	call   0x403720 
   0x0000000000402277 <+171>:	mov    DWORD PTR [rbp-0x8],eax
   0x000000000040227a <+174>:	mov    eax,DWORD PTR [rbp-0x8]
   0x000000000040227d <+177>:	leave  
   0x000000000040227e <+178>:	ret    
End of assembler dump.

The function luaL_loadbuffer loads a buffer as a Lua chunk. This function uses lua_load to load the chunk in the buffer pointed to by buff with size sz.This function returns the same results as lua_load. name is the chunk name, used for debug information and error messages.

int luaL_loadbuffer (lua_State *L,
                     const char *buff,
                     size_t sz,
                     const char *name);

Before calling to luaL_loadbuffer, the registers are configured with the necessary parameters.

   0x000000000040223c <+112>:	mov    ecx,0x41c7e4
   0x0000000000402241 <+117>:	mov    edx,0x1e7
   0x0000000000402246 <+122>:	mov    esi,0x627340
   0x000000000040224b <+127>:	mov    rdi,rax
   0x000000000040224e <+130>:	call   0x411110 

The parameter const char *buf should contain the lua ascii script code. This value is passed to luaL_loadbuffer using the 32 bit register $esi at 0x0000000000402246

gdb-peda$ x/s $esi
0x627340 :	"p = 54111037\ng = 56321\n\nio.write(\"Enter your password: \")\nio.flush()\\nif string.len(password) ~= 32 then\n    print(\"Wrong!\")\n    return 0\nend\n\nv = g\nalpha = \"0123456789abcdef\"\nfor lo"...
0x627408 :	"op =1,32 do\n    v = v * g\n    v = v % p\n    r = v % 16\n    good = string.sub(alpha,r+1,r+1)\n    if good ~= string.sub(password,loop,loop) then\n        print(\"Wrong!\")\n        return 0\n    end\nend\nprin"...
0x6274d0 :	"t(\"Well done, the flag is: ebCTF{\"..password..\"}\")\n-- f02233aca4839124ee6ffa766883c47e\n"

This is the extracted challengue.lua script:

p = 54111037
g = 56321

io.write("Enter your password: ")
if string.len(password) ~= 32 then
    return 0

v = g
alpha = "0123456789abcdef"
for loop =1,32 do
    v = v * g
    v = v % p
    r = v % 16
    good = string.sub(alpha,r+1,r+1)
    if good ~= string.sub(password,loop,loop) then
        return 0

print("Well done, the flag is: ebCTF{\"..password..\"}")
-- f02233aca4839124ee6ffa766883c47e

Finally, the challenge gets solved! ;-D $ ./moon 
Enter your password: f02233aca4839124ee6ffa766883c47e
Well done, the flag is: ebCTF{f02233aca4839124ee6ffa766883c47e} $ 
Published inhackinglinux