picoCTF Practice Let's get dynamic をGhidraで解いたが。。。

picoCTF Practice Let's get dynamic
~~本当は，今研修で勉強している gdb を使って解きたかったが，1日勉強したぐらいでは，gdb で stack strings を拝ませてもらうことはできなかった。~~ なので Ghidra で解いた。
~~いつか gdb で解く。~~
gdb を gdb-peda にしたら解けた。


# Let's get dynamic
Description:
Can you tell what this file is reading? [chall.S](https://mercury.picoctf.net/static/13400736ce4da826502bfc6fc44d02eb/chall.S)
Hints:
1. Running this in a debugger would be helpful

```:chall.S
	.file	"chall.c"
	.text
	.section	.rodata
	.align 8
.LC0:
	.string	"Correct! You entered the flag."
.LC1:
	.string	"No, that's not right."
	.text
	.globl	main
	.type	main, @function
main:
.LFB5:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	pushq	%rbx
	subq	$296, %rsp
	.cfi_offset 3, -24
	movl	%edi, -292(%rbp)
	movq	%rsi, -304(%rbp)
	movq	%fs:40, %rax
	movq	%rax, -24(%rbp)
	xorl	%eax, %eax
	movabsq	$4137700413143496212, %rax
	movabsq	$3668774195188830448, %rdx
	movq	%rax, -144(%rbp)
	movq	%rdx, -136(%rbp)
	movabsq	$-3415231997387159298, %rax
	movabsq	$3180240096696696075, %rdx
	movq	%rax, -128(%rbp)
	movq	%rdx, -120(%rbp)
	movabsq	$-5717177924950513641, %rax
	movabsq	$-3967246834314051972, %rdx
	movq	%rax, -112(%rbp)
	movq	%rdx, -104(%rbp)
	movw	$97, -96(%rbp)
	movabsq	$6214777055764401527, %rax
	movabsq	$8184225536171504527, %rdx
	movq	%rax, -80(%rbp)
	movq	%rdx, -72(%rbp)
	movabsq	$-8364134581669616439, %rax
	movabsq	$5916610601309242417, %rdx
	movq	%rax, -64(%rbp)
	movq	%rdx, -56(%rbp)
	movabsq	$-2598080388612165765, %rax
	movabsq	$-4252370736625094538, %rdx
	movq	%rax, -48(%rbp)
	movq	%rdx, -40(%rbp)
	movw	$63, -32(%rbp)
	movq	stdin(%rip), %rdx
	leaq	-208(%rbp), %rax
	movl	$49, %esi
	movq	%rax, %rdi
	call	fgets@PLT
	movl	$0, -276(%rbp)
	jmp	.L2
.L3:
	movl	-276(%rbp), %eax
	cltq
	movzbl	-144(%rbp,%rax), %edx
	movl	-276(%rbp), %eax
	cltq
	movzbl	-80(%rbp,%rax), %eax
	xorl	%eax, %edx
	movl	-276(%rbp), %eax
	xorl	%edx, %eax
	xorl	$19, %eax
	movl	%eax, %edx
	movl	-276(%rbp), %eax
	cltq
	movb	%dl, -272(%rbp,%rax)
	addl	$1, -276(%rbp)
.L2:
	movl	-276(%rbp), %eax
	movslq	%eax, %rbx
	leaq	-144(%rbp), %rax
	movq	%rax, %rdi
	call	strlen@PLT
	cmpq	%rax, %rbx
	jb	.L3
	leaq	-272(%rbp), %rcx
	leaq	-208(%rbp), %rax
	movl	$49, %edx
	movq	%rcx, %rsi
	movq	%rax, %rdi
	call	memcmp@PLT
	testl	%eax, %eax
	je	.L4
	leaq	.LC0(%rip), %rdi
	call	puts@PLT
	movl	$0, %eax
	jmp	.L6
.L4:
	leaq	.LC1(%rip), %rdi
	call	puts@PLT
	movl	$1, %eax
.L6:
	movq	-24(%rbp), %rcx
	xorq	%fs:40, %rcx
	je	.L7
	call	__stack_chk_fail@PLT
.L7:
	addq	$296, %rsp
	popq	%rbx
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE5:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
	.section	.note.GNU-stack,"",@progbits
```

Solution:
とりあえずコンパイルしてみる。

```
$ gcc chall.S
```
# gdbで解く
金曜に勉強し始めた gdb やってみる

```
$ gdb ./a.out
(gdb) br memcmp
Breakpoint 1 at 0x690
(gdb) r
Starting program: /mnt/c/Users/xxx/downloads/a.out
aaa
Correct! You entered the flag.
[Inferior 1 (process 384) exited normally]
```

とまらねー。
いろいろ試したがダメだ。
gdb で解けないのは悔しいが，Ghidraで解く

# Ghidraで解く

```c:main
bool main(void)

{
  int iVar1;
  size_t sVar2;
  long in_FS_OFFSET;
  int local_11c;
  byte local_118 [64];
  char local_d8 [64];
  undefined8 local_98;
  undefined8 local_90;
  undefined8 local_88;
  undefined8 local_80;
  undefined8 local_78;
  undefined8 local_70;
  undefined2 local_68;
  undefined8 local_58;
  undefined8 local_50;
  undefined8 local_48;
  undefined8 local_40;
  undefined8 local_38;
  undefined8 local_30;
  undefined2 local_28;
  long local_20;
  
  local_20 = *(long *)(in_FS_OFFSET + 0x28);
  local_98 = 0x396c109a7067b614;
  local_90 = 0x32ea1ab1495990f0;
  local_88 = 0xd09aa897d230c8fe;
  local_80 = 0x2c227b84b00f7d0b;
  local_78 = 0xb0a880f7d99ea817;
  local_70 = 0xc8f18206086afe7c;
  local_68 = 0x61;
  local_58 = 0x563f52ce0f15cd77;
  local_50 = 0x719435c3652ef38f;
  local_48 = 0x8bec9fe9be05a4c9;
  local_40 = 0x521c05fe8d590431;
  local_38 = 0xdbf1c3a6dadcef7b;
  local_30 = 0xc4fc8b585631f076;
  local_28 = 0x3f;
  fgets(local_d8,0x31,stdin);
  local_11c = 0;
  while( true ) {
    sVar2 = strlen((char *)&local_98);
    if (sVar2 <= (ulong)(long)local_11c) break;
    local_118[local_11c] =
         (byte)local_11c ^
         *(byte *)((long)&local_98 + (long)local_11c) ^ *(byte *)((long)&local_58 + (long)local_11c)
         ^ 0x13;
    local_11c = local_11c + 1;
  }
  iVar1 = memcmp(local_d8,local_118,0x31);
  if (iVar1 == 0) {
    puts("No, that\'s not right.");
  }
  else {
    puts("Correct! You entered the flag.");
  }
  if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return iVar1 == 0;
}
```

local_98 の 変数名を key に
local_58 の 変数名を enc に
local_11c の 変数名を i に
local_118 の 変数名を flag に
local_98 の 型を byte[49] に
local_58 の 型を byte[49] に
変更すると

```c
  i = 0;
  while( true ) {
    sVar2 = strlen((char *)key);
    if (sVar2 <= (ulong)(long)i) break;
    flag[i] = (byte)i ^ key[i] ^ enc[i] ^ 0x13;
    i = i + 1;
  }
  iVar1 = memcmp(local_d8,flag,0x31);
  if (iVar1 == 0) {
    puts("No, that\'s not right.");
  }
  else {
    puts("Correct! You entered the flag.");
  }
```

フラグの復号は i ^ key[i] ^ enc[i] ^ 0x13 ですね。
ソルバー（Ghidra Script）を書く

```python:solver.py
def qword_parse(value):
    #return([(value & 0xff00000000000000) / 0x100000000000000,(value & 0x00ff000000000000) / 0x1000000000000,(value & 0x0000ff0000000000) / 0x10000000000,(value & 0x000000ff00000000) / 0x100000000,(value & 0x00000000ff000000) / 0x1000000,(value & 0x0000000000ff0000) / 0x10000,(value & 0x000000000000ff00) / 0x100,(value & 0x00000000000000ff) / 0x1])
    return([(value & 0x00000000000000ff) / 0x1,(value & 0x000000000000ff00) / 0x100,(value & 0x0000000000ff0000) / 0x10000,(value & 0x00000000ff000000) / 0x1000000,(value & 0x000000ff00000000) / 0x100000000,(value & 0x0000ff0000000000) / 0x10000000000,(value & 0x00ff000000000000) / 0x1000000000000,(value & 0xff00000000000000) / 0x100000000000000])

key=[]
inst = getInstructionAt(toAddr(0x001007f2))
key.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = inst.getNext()
key.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = getInstructionAt(toAddr(0x00100814))
key.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = inst.getNext()
key.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = getInstructionAt(toAddr(0x00100830))
key.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = inst.getNext()
key.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = getInstructionAt(toAddr(0x0010084c))
key.append(inst.getOpObjects(1)[0].getValue())
print(key)
print("key="+''.join(map(chr,key)))

enc=[]
inst = getInstructionAt(toAddr(0x00100852))
enc.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = inst.getNext()
enc.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = getInstructionAt(toAddr(0x0010086e))
enc.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = inst.getNext()
enc.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = getInstructionAt(toAddr(0x0010088a))
enc.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = inst.getNext()
enc.extend(qword_parse(inst.getOpObjects(1)[0].getValue()))
inst = getInstructionAt(toAddr(0x001008a6))
enc.append(inst.getOpObjects(1)[0].getValue())
print(enc)
print("enc="+''.join(map(chr,enc)))

ans=[]
i = 0
while i < 49:
    ans.append( i ^ enc[i] ^ key[i] ^ 0x13 )
    i = i + 1
print(ans)
print("ans="+''.join(map(chr,ans)))
```

結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/6d28c5b4-2d5a-8704-bc3f-c03247f09bbc.png)

# gdb-peda で解く

まずインストールでお世話になったサイト

https://qiita.com/miyase256/items/248a486cca671686c58c

gdb実行

```
$ gdb -q ./a.out
Reading symbols from ./a.out...(no debugging symbols found)...done.
```

main　にブレークポイントしかけて実行

```
gdb-peda$ b main
Breakpoint 1 at 0x7ce
gdb-peda$ r
Breakpoint 1, 0x00000000080007ce in main ()
```

main関数を確認

```
gdb-peda$ pdisass main
Dump of assembler code for function main:
   0x00000000080007ca <+0>:     push   rbp
   0x00000000080007cb <+1>:     mov    rbp,rsp
=> 0x00000000080007ce <+4>:     push   rbx
   0x00000000080007cf <+5>:     sub    rsp,0x128
   0x00000000080007d6 <+12>:    mov    DWORD PTR [rbp-0x124],edi
   0x00000000080007dc <+18>:    mov    QWORD PTR [rbp-0x130],rsi
   0x00000000080007e3 <+25>:    mov    rax,QWORD PTR fs:0x28
   0x00000000080007ec <+34>:    mov    QWORD PTR [rbp-0x18],rax
   0x00000000080007f0 <+38>:    xor    eax,eax
   0x00000000080007f2 <+40>:    movabs rax,0x396c109a7067b614
   0x00000000080007fc <+50>:    movabs rdx,0x32ea1ab1495990f0
   0x0000000008000806 <+60>:    mov    QWORD PTR [rbp-0x90],rax
   0x000000000800080d <+67>:    mov    QWORD PTR [rbp-0x88],rdx
   0x0000000008000814 <+74>:    movabs rax,0xd09aa897d230c8fe
   0x000000000800081e <+84>:    movabs rdx,0x2c227b84b00f7d0b
   0x0000000008000828 <+94>:    mov    QWORD PTR [rbp-0x80],rax
   0x000000000800082c <+98>:    mov    QWORD PTR [rbp-0x78],rdx
   0x0000000008000830 <+102>:   movabs rax,0xb0a880f7d99ea817
   0x000000000800083a <+112>:   movabs rdx,0xc8f18206086afe7c
   0x0000000008000844 <+122>:   mov    QWORD PTR [rbp-0x70],rax
   0x0000000008000848 <+126>:   mov    QWORD PTR [rbp-0x68],rdx
   0x000000000800084c <+130>:   mov    WORD PTR [rbp-0x60],0x61
   0x0000000008000852 <+136>:   movabs rax,0x563f52ce0f15cd77
   0x000000000800085c <+146>:   movabs rdx,0x719435c3652ef38f
   0x0000000008000866 <+156>:   mov    QWORD PTR [rbp-0x50],rax
   0x000000000800086a <+160>:   mov    QWORD PTR [rbp-0x48],rdx
   0x000000000800086e <+164>:   movabs rax,0x8bec9fe9be05a4c9
   0x0000000008000878 <+174>:   movabs rdx,0x521c05fe8d590431
   0x0000000008000882 <+184>:   mov    QWORD PTR [rbp-0x40],rax
   0x0000000008000886 <+188>:   mov    QWORD PTR [rbp-0x38],rdx
   0x000000000800088a <+192>:   movabs rax,0xdbf1c3a6dadcef7b
   0x0000000008000894 <+202>:   movabs rdx,0xc4fc8b585631f076
   0x000000000800089e <+212>:   mov    QWORD PTR [rbp-0x30],rax
   0x00000000080008a2 <+216>:   mov    QWORD PTR [rbp-0x28],rdx
   0x00000000080008a6 <+220>:   mov    WORD PTR [rbp-0x20],0x3f
   0x00000000080008ac <+226>:   mov    rdx,QWORD PTR [rip+0x20075d]        # 0x8201010 <stdin@@GLIBC_2.2.5>
   0x00000000080008b3 <+233>:   lea    rax,[rbp-0xd0]
   0x00000000080008ba <+240>:   mov    esi,0x31
   0x00000000080008bf <+245>:   mov    rdi,rax
   0x00000000080008c2 <+248>:   call   0x80006a0 <fgets@plt>
   0x00000000080008c7 <+253>:   mov    DWORD PTR [rbp-0x114],0x0
   0x00000000080008d1 <+263>:   jmp    0x8000915 <main+331>
   0x00000000080008d3 <+265>:   mov    eax,DWORD PTR [rbp-0x114]
   0x00000000080008d9 <+271>:   cdqe
   0x00000000080008db <+273>:   movzx  edx,BYTE PTR [rbp+rax*1-0x90]
   0x00000000080008e3 <+281>:   mov    eax,DWORD PTR [rbp-0x114]
   0x00000000080008e9 <+287>:   cdqe
   0x00000000080008eb <+289>:   movzx  eax,BYTE PTR [rbp+rax*1-0x50]
   0x00000000080008f0 <+294>:   xor    edx,eax
   0x00000000080008f2 <+296>:   mov    eax,DWORD PTR [rbp-0x114]
   0x00000000080008f8 <+302>:   xor    eax,edx
   0x00000000080008fa <+304>:   xor    eax,0x13
   0x00000000080008fd <+307>:   mov    edx,eax
   0x00000000080008ff <+309>:   mov    eax,DWORD PTR [rbp-0x114]
   0x0000000008000905 <+315>:   cdqe
   0x0000000008000907 <+317>:   mov    BYTE PTR [rbp+rax*1-0x110],dl
   0x000000000800090e <+324>:   add    DWORD PTR [rbp-0x114],0x1
   0x0000000008000915 <+331>:   mov    eax,DWORD PTR [rbp-0x114]
   0x000000000800091b <+337>:   movsxd rbx,eax
   0x000000000800091e <+340>:   lea    rax,[rbp-0x90]
   0x0000000008000925 <+347>:   mov    rdi,rax
   0x0000000008000928 <+350>:   call   0x8000670 <strlen@plt>
   0x000000000800092d <+355>:   cmp    rbx,rax
   0x0000000008000930 <+358>:   jb     0x80008d3 <main+265>
   0x0000000008000932 <+360>:   lea    rcx,[rbp-0x110]
   0x0000000008000939 <+367>:   lea    rax,[rbp-0xd0]
   0x0000000008000940 <+374>:   mov    edx,0x31
   0x0000000008000945 <+379>:   mov    rsi,rcx
   0x0000000008000948 <+382>:   mov    rdi,rax
   0x000000000800094b <+385>:   call   0x8000690 <memcmp@plt>
   0x0000000008000950 <+390>:   test   eax,eax
   0x0000000008000952 <+392>:   je     0x8000967 <main+413>
   0x0000000008000954 <+394>:   lea    rdi,[rip+0xcd]        # 0x8000a28
   0x000000000800095b <+401>:   call   0x8000660 <puts@plt>
   0x0000000008000960 <+406>:   mov    eax,0x0
   0x0000000008000965 <+411>:   jmp    0x8000978 <main+430>
   0x0000000008000967 <+413>:   lea    rdi,[rip+0xd9]        # 0x8000a47
   0x000000000800096e <+420>:   call   0x8000660 <puts@plt>
   0x0000000008000973 <+425>:   mov    eax,0x1
   0x0000000008000978 <+430>:   mov    rcx,QWORD PTR [rbp-0x18]
   0x000000000800097c <+434>:   xor    rcx,QWORD PTR fs:0x28
   0x0000000008000985 <+443>:   je     0x800098c <main+450>
   0x0000000008000987 <+445>:   call   0x8000680 <__stack_chk_fail@plt>
   0x000000000800098c <+450>:   add    rsp,0x128
   0x0000000008000993 <+457>:   pop    rbx
   0x0000000008000994 <+458>:   pop    rbp
   0x0000000008000995 <+459>:   ret
End of assembler dump.
```

0x8000932にブレークポイントを設定すれば，復号が終わってる

```
gdb-peda$ b *0x8000932
Breakpoint 2 at 0x8000932
gdb-peda$ c
Continuing.

```

入力待ちになるので適当な文字を入力

```
aaa
[----------------------------------registers-----------------------------------]
RAX: 0x31 ('1')
RBX: 0x31 ('1')
RCX: 0x0
RDX: 0xc0fe000000000000
RSI: 0x7ffffffee1a0 --> 0x7f000a616161
RDI: 0x7ffffffee1e0 --> 0x396c109a7067b614
RBP: 0x7ffffffee270 --> 0x80009a0 --> 0x41d7894956415741
RSP: 0x7ffffffee140 --> 0x7ffffffee358 --> 0x7ffffffee57f ("/mnt/c/Users/xxx/Downloads/a.out")
RIP: 0x8000932 --> 0x48fffffef08d8d48
R8 : 0x0
R9 : 0x7fffff16e6a0 (<__memcpy_ssse3+8208>:     mov    dx,WORD PTR [rsi-0x3])
R10: 0x8402010 --> 0x0
R11: 0x7fffff1bce60 --> 0xfffb1480fffb12b8
R12: 0x80006c0 --> 0x89485ed18949ed31
R13: 0x7ffffffee350 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8000928 <main+350>:        call   0x8000670 <strlen@plt>
   0x800092d <main+355>:        cmp    rbx,rax
   0x8000930 <main+358>:        jb     0x80008d3 <main+265>
=> 0x8000932 <main+360>:        lea    rcx,[rbp-0x110]
   0x8000939 <main+367>:        lea    rax,[rbp-0xd0]
   0x8000940 <main+374>:        mov    edx,0x31
   0x8000945 <main+379>:        mov    rsi,rcx
   0x8000948 <main+382>:        mov    rdi,rax
[------------------------------------stack-------------------------------------]
0000| 0x7ffffffee140 --> 0x7ffffffee358 --> 0x7ffffffee57f ("/mnt/c/Users/xxx/Downloads/a.out")
0008| 0x7ffffffee148 --> 0x1ff62b710
0016| 0x7ffffffee150 --> 0x0
0024| 0x7ffffffee158 --> 0x31ff40b39f
0032| 0x7ffffffee160 ("picoCTF{dyn4m1c_4n4ly1s_1s_5up3r_us3ful_14bfa700}7\033\377\377\177")
0040| 0x7ffffffee168 ("dyn4m1c_4n4ly1s_1s_5up3r_us3ful_14bfa700}7\033\377\377\177")
0048| 0x7ffffffee170 ("4n4ly1s_1s_5up3r_us3ful_14bfa700}7\033\377\377\177")
0056| 0x7ffffffee178 ("1s_5up3r_us3ful_14bfa700}7\033\377\377\177")
[------------------------------------------------------------------------------]
```

ビンゴ