picoCTF 2021 writeup
picoCTF 2021にソロで参加して27/88問に解答しました。得点はメモしてなかったので不明です。 開催期間が結構長かったのに数日しか参加出来なかったので悲しい。
メモが残っていた問題のwriteup
ARMssembly 0
問題文は以下の通り。ARMv8のアセンブリが渡されて、このプログラムの引数が"4112417903"と"1169092511"である場合に出力される値を答える問題。
Description What integer does this program print with arguments 4112417903 and 1169092511? File: chall.S Flag format: picoCTF{XXXXXXXX} -> (hex, lowercase, no 0x, and 32 bits. ex. 5614267 would be picoCTF{0055aabb})
ソースファイル(chall.S)が提供される。
.arch armv8-a .file "chall.c" .text .align 2 .global func1 .type func1, %function func1: sub sp, sp, #16 str w0, [sp, 12] str w1, [sp, 8] ldr w1, [sp, 12] ldr w0, [sp, 8] cmp w1, w0 bls .L2 ldr w0, [sp, 12] b .L3 .L2: ldr w0, [sp, 8] .L3: add sp, sp, 16 ret .size func1, .-func1 .section .rodata .align 3 .LC0: .string "Result: %ld\n" .text .align 2 .global main .type main, %function main: stp x29, x30, [sp, -48]! add x29, sp, 0 str x19, [sp, 16] str w0, [x29, 44] str x1, [x29, 32] ldr x0, [x29, 32] add x0, x0, 8 ldr x0, [x0] bl atoi mov w19, w0 # w19 = 4112417903 ldr x0, [x29, 32] add x0, x0, 16 ldr x0, [x0] bl atoi mov w1, w0 # w1 = 1169092511 mov w0, w19 # w0 = 4112417903 bl func1 mov w1, w0 adrp x0, .LC0 add x0, x0, :lo12:.LC0 bl printf mov w0, 0 ldr x19, [sp, 16] ldp x29, x30, [sp], 48 ret .size main, .-main .ident "GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0" .section .note.GNU-stack,"",@progbits
main関数のbl命令でfunc1関数を実行して、実行結果をprintf関数で出力すると思われる。
stp x29, x30, [sp, -48]! add x29, sp, 0 str x19, [sp, 16] str w0, [x29, 44] str x1, [x29, 32] ldr x0, [x29, 32] add x0, x0, 8 ldr x0, [x0] bl atoi # atoi関数 mov w19, w0 # w19 = 4112417903 ldr x0, [x29, 32] add x0, x0, 16 ldr x0, [x0] bl atoi # atoi関数 mov w1, w0 # w1 = 1169092511 mov w0, w19 # w0 = 4112417903 bl func1 # func1関数(引数1 : 4112417903, 引数2 : 1169092511) mov w1, w0 adrp x0, .LC0 # "Result: %ld\n" add x0, x0, :lo12:.LC0 bl printf
問題文にある引数を与えた場合、func1関数の返り値として、w0には4112417903が格納される。
func1: sub sp, sp, #16 str w0, [sp, 12] # w0(4112417903) -> [sp, 12] str w1, [sp, 8] # w1(1169092511) -> [sp, 8] ldr w1, [sp, 12] # w1 <- [sp, 12](4112417903) ldr w0, [sp, 8] # w0 <- [sp, 8](1169092511) cmp w1, w0 # 4112417903, 1169092511 bls .L2 # not jump ldr w0, [sp, 12] # w0 <- [sp, 12](4112417903) b .L3 .L2: ldr w0, [sp, 8] .L3: add sp, sp, 16 ret .size func1, .-func1 .section .rodata .align 3
問題文の指定より、フラグは16進数表記、プレフィックス無しの形式になる。
C:\Users\user>python Python 2.7.16 (v2.7.16:413a49145e, Mar 4 2019, 01:37:19) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> hex(4112417903) '0xf51e846fL'
Flag : picoCTF{f51e846f}
ARMssembly 1
問題文は以下の通り。ARMv8のアセンブリが渡されて、このプログラムにどのような引数が与えられた時に win
が出力されるのかを答える問題。
For what argument does this program print `win` with variables 81, 0 and 3? File: chall_1.S Flag format: picoCTF{XXXXXXXX} -> (hex, lowercase, no 0x, and 32 bits. ex. 5614267 would be picoCTF{0055aabb})
ソースファイル(chall_1.S)が提供される。
.arch armv8-a .file "chall_1.c" .text .align 2 .global func .type func, %function func: sub sp, sp, #32 str w0, [sp, 12] mov w0, 81 str w0, [sp, 16] str wzr, [sp, 20] mov w0, 3 str w0, [sp, 24] ldr w0, [sp, 20] ldr w1, [sp, 16] lsl w0, w1, w0 str w0, [sp, 28] ldr w1, [sp, 28] ldr w0, [sp, 24] sdiv w0, w1, w0 str w0, [sp, 28] ldr w1, [sp, 28] ldr w0, [sp, 12] sub w0, w1, w0 str w0, [sp, 28] ldr w0, [sp, 28] add sp, sp, 32 ret .size func, .-func .section .rodata .align 3 .LC0: .string "You win!" .align 3 .LC1: .string "You Lose :(" .text .align 2 .global main .type main, %function main: stp x29, x30, [sp, -48]! add x29, sp, 0 str w0, [x29, 28] str x1, [x29, 16] ldr x0, [x29, 16] add x0, x0, 8 ldr x0, [x0] bl atoi str w0, [x29, 44] ldr w0, [x29, 44] bl func cmp w0, 0 bne .L4 adrp x0, .LC0 add x0, x0, :lo12:.LC0 bl puts b .L6 .L4: adrp x0, .LC1 add x0, x0, :lo12:.LC1 bl puts .L6: nop ldp x29, x30, [sp], 48 ret .size main, .-main .ident "GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0" .section .note.GNU-stack,"",@progbits
func関数に与えられた値の動きを確認する。問題文にある通り、81、0、3が関数内で使用されている。また、 sub w0, w1, w0
でfunc関数の引数が計算に使用されている。
func: sub sp, sp, #32 str w0, [sp, 12] # w0(★funcの引数) -> [sp, 12] mov w0, 81 # w0 = 81 str w0, [sp, 16] # w0(81) -> [sp, 16] str wzr, [sp, 20] # wzr(zero_register) -> [sp, 20] mov w0, 3 # w0 = 3 str w0, [sp, 24] # w0(3) -> [sp, 24] ldr w0, [sp, 20] # w0 <- [sp, 20](0) ldr w1, [sp, 16] # w1 <- [sp, 16](81) lsl w0, w1, w0 # w0(81) <- 81 << 0 str w0, [sp, 28] # w0(81) -> [sp, 28] ldr w1, [sp, 28] # w1 <- [sp, 28](81) ldr w0, [sp, 24] # w0 <- [sp, 24](3) sdiv w0, w1, w0 # w0(27) <- w1(81) / w0(3) str w0, [sp, 28] # w0(27) -> [sp, 28] ldr w1, [sp, 28] # w1 <- [sp, 28](27) ldr w0, [sp, 12] # w0 <- ★funcの引数 sub w0, w1, w0 # w0 <- w1(27) - w0(★funcの引数) str w0, [sp, 28] ldr w0, [sp, 28] # w0 = "w1(27) - w0(★funcの引数)"の計算結果 add sp, sp, 32 ret .size func, .-func .section .rodata .align 3
func関数以降のコードを確認すると、返り値が0と等しくない時に.L4にジャンプして"You Lose :("を出力する。"You win!"と出力されるのはfunc関数の返り値(w0)が0の場合になる。
bl func cmp w0, 0 bne .L4 adrp x0, .LC0 # "You win!" add x0, x0, :lo12:.LC0 bl puts b .L6
func関数の sub w0, w1, w0
の実行結果が0になるのはfunc関数の引数が27の場合。
C:\Users\user>python Python 2.7.16 (v2.7.16:413a49145e, Mar 4 2019, 01:37:19) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> hex(27) '0x1b'
FLAG : picoCTF{0000001b}
ARMssembly 2
問題文は以下の通り。ARMv8のアセンブリが渡されて、このプログラムに与えられる引数が2610164910の時に出力される値を答える。
Description What integer does this program print with argument 2610164910? File: chall_2.S Flag format: picoCTF{XXXXXXXX} -> (hex, lowercase, no 0x, and 32 bits. ex. 5614267 would be picoCTF{0055aabb})
アセンブリファイル(chall_2.S)の内容は以下の通り。
.arch armv8-a .file "chall_2.c" .text .align 2 .global func1 .type func1, %function func1: sub sp, sp, #32 str w0, [sp, 12] str wzr, [sp, 24] str wzr, [sp, 28] b .L2 .L3: ldr w0, [sp, 24] add w0, w0, 3 str w0, [sp, 24] ldr w0, [sp, 28] add w0, w0, 1 str w0, [sp, 28] .L2: ldr w1, [sp, 28] ldr w0, [sp, 12] cmp w1, w0 bcc .L3 ldr w0, [sp, 24] add sp, sp, 32 ret .size func1, .-func1 .section .rodata .align 3 .LC0: .string "Result: %ld\n" .text .align 2 .global main .type main, %function main: stp x29, x30, [sp, -48]! add x29, sp, 0 str w0, [x29, 28] str x1, [x29, 16] ldr x0, [x29, 16] add x0, x0, 8 ldr x0, [x0] bl atoi bl func1 str w0, [x29, 44] adrp x0, .LC0 add x0, x0, :lo12:.LC0 ldr w1, [x29, 44] bl printf nop ldp x29, x30, [sp], 48 ret .size main, .-main .ident "GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0" .section .note.GNU-stack,"",@progbits
L3では[sp, 24]が3ずつ、[sp, 28]が1ずつ増加する。
func1: sub sp, sp, #32 str w0, [sp, 12] # w0(2610164910) -> [sp, 12] str wzr, [sp, 24] # wzr(0) -> [sp, 24] str wzr, [sp, 28] # wzr(0) -> [sp, 28] b .L2 # jump to .L2 .L3: ldr w0, [sp, 24] # w0 <- [sp, 24](0) add w0, w0, 3 # w0 <- w0(0) + 3 str w0, [sp, 24] # w0(3) -> [sp, 24] ldr w0, [sp, 28] # w0 <- [sp, 28](0) add w0, w0, 1 # w0 <- w0(0) + 1 str w0, [sp, 28] # w0(1) -> [sp, 28] .L2: ldr w1, [sp, 28] # w1 <- [sp, 28](0) ldr w0, [sp, 12] # w0 <- [sp, 12](2610164910) cmp w1, w0 bcc .L3 ldr w0, [sp, 24] add sp, sp, 32 ret .size func1, .-func1 .section .rodata .align 3
func1関数ではループカウンタ([sp, 28])が引数の値(2610164910)と一致するまでループが行われて、[sp, 24]の値が3ずつ増加する。そのため、ループを抜ける時の[sp, 24]の値がfunc1関数の返り値になる。[sp, 24]の値は 2610164910 * 3 = 7830494730
になる。
C:\Users\user>python Python 2.7.16 (v2.7.16:413a49145e, Mar 4 2019, 01:37:19) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> w0 = 2610164910 * 3 >>> hex(w0) '0x1d2bbde0aL' >>> flag = 0x1d2bbde0a & 0xffffffff >>> hex(flag) '0xd2bbde0aL'
FLAG : picoCTF{d2bbde0a}
ARMssembly 3
問題文は以下の通り。ARMv8のアセンブリが渡されて、このプログラムに与えられる引数が469937816の時に出力される値を答える。
Description What integer does this program print with argument 469937816? File: chall_3.S Flag format: picoCTF{XXXXXXXX} -> (hex, lowercase, no 0x, and 32 bits. ex. 5614267 would be picoCTF{0055aabb})
与えられたファイル(chall_3.S)を確認する。
L2では[x29, 28]が0では無い場合、ループを実行する。[x29, 28]の値と0x01のAND演算の結果を取得して、演算結果が0の時はL3(1バイトの右シフト演算を行う)にジャンプする。演算結果が0以外の時はfunc2関数(カウンタとして使用している[x29, 44]に3を加算する)を実行する。
まとめると、[x29, 28]が0になるまでAND演算と右シフト演算を繰り返し、その中でAND演算の結果が0以外になったタイミングではカウンタに3を加算する。このカウンタの値がfunc1関数の返り値になるので、これを求める。
.arch armv8-a .file "chall_3.c" .text .align 2 .global func1 .type func1, %function func1: stp x29, x30, [sp, -48]! add x29, sp, 0 str w0, [x29, 28] # w0(469937816) -> [x29, 28] str wzr, [x29, 44] # wzr(0) -> [x29, 44] b .L2 .L4: ldr w0, [x29, 28] # w0 <- [x29, 28](469937816) and w0, w0, 1 # w0 <- 469937816 and 1 cmp w0, 0 beq .L3 ldr w0, [x29, 44] bl func2 str w0, [x29, 44] .L3: ldr w0, [x29, 28] # w0 <- [x29, 28](469937816) lsr w0, w0, 1 # w0(234968908) <- 469937816 >> 1 str w0, [x29, 28] # w0(234968908) -> [x29, 28] .L2: ldr w0, [x29, 28] # w0 <- [x29, 28](469937816) cmp w0, 0 bne .L4 ldr w0, [x29, 44] ldp x29, x30, [sp], 48 ret .size func1, .-func1 .align 2 .global func2 .type func2, %function func2: sub sp, sp, #16 str w0, [sp, 12] ldr w0, [sp, 12] add w0, w0, 3 # w0 <- w0 + 3 add sp, sp, 16 ret .size func2, .-func2 .section .rodata .align 3 .LC0: .string "Result: %ld\n" .text .align 2 .global main .type main, %function main: stp x29, x30, [sp, -48]! add x29, sp, 0 str w0, [x29, 28] str x1, [x29, 16] ldr x0, [x29, 16] add x0, x0, 8 ldr x0, [x0] bl atoi bl func1 # func1(469937816) str w0, [x29, 44] adrp x0, .LC0 add x0, x0, :lo12:.LC0 ldr w1, [x29, 44] bl printf nop ldp x29, x30, [sp], 48 ret .size main, .-main .ident "GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0" .section .note.GNU-stack,"",@progbits
計算すると最終的にカウンタの値は36になる。
C:\Users\user>python Python 2.7.16 (v2.7.16:413a49145e, Mar 4 2019, 01:37:19) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> hex(36) '0x24'
FLAG : picoCTF{00000024}
ARMssembly 4
問題文は以下の通り。ARMv8のアセンブリが渡されて、このプログラムに与えられる引数が3434881889の時に出力される値を答える。
Description What integer does this program print with argument 3434881889? File: chall_4.S Flag format: picoCTF{XXXXXXXX} -> (hex, lowercase, no 0x, and 32 bits. ex. 5614267 would be picoCTF{0055aabb})
chall_4.Sを読むと、func1の引数が3434881889の場合、func1を実行 -> 引数に100を加算 -> func2を実行 -> 引数に13を加算 -> func5を実行 -> func8を実行 -> 引数に2を加算 -> 演算結果を返り値とする -> func1の返り値を出力
という流れで動作することが分かる。
.arch armv8-a .file "chall_4.c" .text .align 2 .global func1 .type func1, %function func1: stp x29, x30, [sp, -32]! add x29, sp, 0 str w0, [x29, 28] ldr w0, [x29, 28] # w0 <- [x29, 28](3434881889) cmp w0, 100 bls .L2 # not jump ldr w0, [x29, 28] add w0, w0, 100 # w0(3434881989) <- w0(3434881889) + 100 bl func2 # func2(3434881989) b .L3 .L2: ldr w0, [x29, 28] bl func3 .L3: ldp x29, x30, [sp], 32 ret .size func1, .-func1 .align 2 .global func2 .type func2, %function func2: stp x29, x30, [sp, -32]! add x29, sp, 0 str w0, [x29, 28] ldr w0, [x29, 28] # w0 <- [x29, 28](3434881989) cmp w0, 499 bhi .L5 # jump to L5 ldr w0, [x29, 28] sub w0, w0, #86 bl func4 b .L6 .L5: ldr w0, [x29, 28] # w0 <- [x29, 28](3434881989) add w0, w0, 13 # w0(3434882002) <- w0(3434881989) + 13 bl func5 # func5(3434882002) .L6: ldp x29, x30, [sp], 32 ret .size func2, .-func2 .align 2 .global func3 .type func3, %function func3: stp x29, x30, [sp, -32]! add x29, sp, 0 str w0, [x29, 28] ldr w0, [x29, 28] bl func7 ldp x29, x30, [sp], 32 ret .size func3, .-func3 .align 2 .global func4 .type func4, %function func4: stp x29, x30, [sp, -48]! add x29, sp, 0 str w0, [x29, 28] mov w0, 17 str w0, [x29, 44] ldr w0, [x29, 44] bl func1 str w0, [x29, 44] ldr w0, [x29, 28] ldp x29, x30, [sp], 48 ret .size func4, .-func4 .align 2 .global func5 .type func5, %function func5: stp x29, x30, [sp, -32]! add x29, sp, 0 str w0, [x29, 28] ldr w0, [x29, 28] # w0 <- [x29, 28](3434882002) bl func8 # func8(3434882002) str w0, [x29, 28] ldr w0, [x29, 28] ldp x29, x30, [sp], 32 ret .size func5, .-func5 .align 2 .global func6 .type func6, %function func6: sub sp, sp, #32 str w0, [sp, 12] mov w0, 314 str w0, [sp, 24] mov w0, 1932 str w0, [sp, 28] str wzr, [sp, 20] str wzr, [sp, 20] b .L14 .L15: ldr w1, [sp, 28] mov w0, 800 mul w0, w1, w0 ldr w1, [sp, 24] udiv w2, w0, w1 ldr w1, [sp, 24] mul w1, w2, w1 sub w0, w0, w1 str w0, [sp, 12] ldr w0, [sp, 20] add w0, w0, 1 str w0, [sp, 20] .L14: ldr w0, [sp, 20] cmp w0, 899 bls .L15 ldr w0, [sp, 12] add sp, sp, 32 ret .size func6, .-func6 .align 2 .global func7 .type func7, %function func7: sub sp, sp, #16 str w0, [sp, 12] ldr w0, [sp, 12] cmp w0, 100 bls .L18 ldr w0, [sp, 12] b .L19 .L18: mov w0, 7 .L19: add sp, sp, 16 ret .size func7, .-func7 .align 2 .global func8 .type func8, %function func8: sub sp, sp, #16 str w0, [sp, 12] ldr w0, [sp, 12] add w0, w0, 2 # w0(3434882004) <- w0(3434882002) + 2 add sp, sp, 16 ret .size func8, .-func8 .section .rodata .align 3 .LC0: .string "Result: %ld\n" .text .align 2 .global main .type main, %function main: stp x29, x30, [sp, -48]! add x29, sp, 0 str w0, [x29, 28] str x1, [x29, 16] ldr x0, [x29, 16] add x0, x0, 8 ldr x0, [x0] bl atoi str w0, [x29, 44] ldr w0, [x29, 44] bl func1 # func1(3434881889) mov w1, w0 adrp x0, .LC0 add x0, x0, :lo12:.LC0 bl printf nop ldp x29, x30, [sp], 48 ret .size main, .-main .ident "GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0" .section .note.GNU-stack,"",@progbits
引数の値(3434881889)に115を加算した値がフラグになる。
C:\Users\user>python Python 2.7.16 (v2.7.16:413a49145e, Mar 4 2019, 01:37:19) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> flag = 3434881889 + 115 >>> hex(flag) '0xccbc23d4L'
Flag : picoCTF{ccbc23d4}
Let's get dynamic
問題文は以下の通り。アセンブリファイル(chall.S)が渡される
Description Can you tell what this file is reading? chall.S
与えられたファイルは以下の通り。読むのが面倒臭そうに思える。
.file "chall.c" .text .section .rodata .align 8 .LC1: .string "Correct! You entered the flag." .LC2: .string "No, that's not right." .align 8 .LC0: .string "\002qs\312\307*\207\375\313-\370\371+\361\025I\020<" .string "TL\r\357\247C\250\002M\367\314\231\223\327\210\226\230\030\370\306*\205LX3\312\353Q\237\347" .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 movq .LC0(%rip), %rax movq 8+.LC0(%rip), %rdx movq %rax, -144(%rbp) movq %rdx, -136(%rbp) movq 16+.LC0(%rip), %rax movq 24+.LC0(%rip), %rdx movq %rax, -128(%rbp) movq %rdx, -120(%rbp) movq 32+.LC0(%rip), %rax movq 40+.LC0(%rip), %rdx movq %rax, -112(%rbp) movq %rdx, -104(%rbp) movzwl 48+.LC0(%rip), %eax movw %ax, -96(%rbp) movabsq $-7866547665503188383, %rax movabsq $750938240303713972, %rdx movq %rax, -80(%rbp) movq %rdx, -72(%rbp) movabsq $-245100717349187545, %rax movabsq $-1321891645065211527, %rdx movq %rax, -64(%rbp) movq %rdx, -56(%rbp) movabsq $4728704058583732155, %rax movabsq $-7828694793552836984, %rdx movq %rax, -48(%rbp) movq %rdx, -40(%rbp) movw $185, -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 .LC1(%rip), %rdi call puts@PLT movl $0, %eax jmp .L6 .L4: leaq .LC2(%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
動的解析を行うことを推奨しているような問題名なので、与えられたファイルをgccでコンパイルする。
gcc chall.S -o chall
challを実行してFlagでは無い文字列を入力しても"Correct! You entered the flag."という文字列が出力される。
root@DESKTOP-G3LRDHC:/mnt/d/CTF/picoCTF2021/Let's get dynamic# ./chall aaa Correct! You entered the flag.
ltraceコマンドの結果より、memcmpで何らかの比較処理を行っているようなのでこの辺りを確認する。
root@DESKTOP-G3LRDHC:/mnt/d/CTF/picoCTF2021/Let's get dynamic# ltrace -i ./chall [0x7f8e550008ba] fgets(aaa "aaa\n", 49, 0x7f8e54beba00) = 0x7ffff4cea420 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000920] strlen("\002qs\312\307*\207\375\313-\370\371+\361\025I\020<") = 18 [0x7f8e55000943] memcmp(0x7ffff4cea420, 0x7ffff4cea3e0, 49, 0x7ffff4cea3e0) = 0xfffffff1 [0x7f8e55000953] puts("Correct! You entered the flag."Correct! You entered the flag. ) = 31 [0xffffffffffffffff] +++ exited (status 0) +++
challのコードを確認したところ、2種類のハードコードされた値とループカウンタと0x13をXORしていることが分かった。
import sys key1 = [0x02, 0x71, 0x73, 0xCA, 0xC7, 0x2A, 0x87, 0xFD, 0xCB, 0x2D, 0xF8, 0xF9, 0x2B, 0xF1, 0x15, 0x49, 0x10, 0x3C, 0x00, 0x54, 0x4C, 0x0D, 0xEF, 0xA7, 0x43, 0xA8, 0x02, 0x4D, 0xF7, 0xCC, 0x99, 0x93, 0xD7, 0x88, 0x96, 0x98, 0x18, 0xF8, 0xC6, 0x2A, 0x85, 0x4C, 0x58, 0x33, 0xCA, 0xEB, 0x51, 0x9F, 0xE7] key2 = [0x61, 0x0A, 0x01, 0xB5, 0x93, 0x68, 0xD4, 0x92, 0xB4, 0x4E, 0x8F, 0xD5, 0x59, 0xDE, 0x6B, 0x0A, 0x27, 0x50, 0x35, 0x38, 0x32, 0x3A, 0x99, 0xFC, 0x79, 0xD1, 0x54, 0x70, 0x8D, 0xB2, 0xA7, 0xED, 0xBB, 0xCF, 0xD4, 0x9B, 0x49, 0xBB, 0x9F, 0x41, 0x88, 0x46, 0x55, 0x3F, 0x90, 0xE3, 0x5A, 0x93, 0xB9] for i in range(len(key1)): temp = key1[i] ^ key2[i] ^ i ^ 0x13 sys.stdout.write((chr(temp)))
Pythonスクリプトで同じ処理を行うことでフラグが得られた。
# root@DESKTOP-G3LRDHC:/mnt/c/Users/hamasho/Desktop# python solver.py picoCTF{dyn4m1c_4n4ly1s_1s_5up3r_us3ful_6044e660}
Flag : picoCTF{dyn4m1c_4n4ly1s_1s_5up3r_us3ful_6044e660}
gogo
与えられたファイルはGolangバイナリっぽい。objdumpやGhidraで解析することが推奨されている。
Description Hmmm this is a weird file... enter_password. There is a instance of the service running at mercury.picoctf.net:4052. Hints use go tool objdump or ghidra
ざっと眺めると以下のような関数が見つかる。
main_checkPassword : 1回目の入力値の処理っぽい main_ambush : 2回目の入力値の処理っぽい
main_checkPassword関数では入力値とハードコードされた値(861836f13e3d627dfa375bdb8389214e)をXORした結果がmain_statictmp_4と等しいかを確認している。ハードコードされた値とmain_statictmp_4をXORして期待される入力値を確認する。入力するべき値は"reverseengineericanbarelyforward"であることが分かる。
import sys key1 = [0x4A, 0x53, 0x47, 0x5D, 0x41, 0x45, 0x03, 0x54, 0x5D, 0x02, 0x5A, 0x0A, 0x53, 0x57, 0x45, 0x0D, 0x05, 0x00, 0x5D, 0x55, 0x54, 0x10, 0x01, 0x0E, 0x41, 0x55, 0x57, 0x4B, 0x45, 0x50, 0x46, 0x01] key2 = [0x38, 0x36, 0x31, 0x38, 0x33, 0x36, 0x66, 0x31, 0x33, 0x65, 0x33, 0x64, 0x36, 0x32, 0x37, 0x64, 0x66, 0x61, 0x33, 0x37, 0x35, 0x62, 0x64, 0x62, 0x38, 0x33, 0x38, 0x39, 0x32, 0x31, 0x34, 0x65] for i in range(len(key1)): temp = key1[i] ^ key2[i] sys.stdout.write((chr(temp)))
enter_passwordを実行して、パスワードとしてreverseengineericanbarelyforwardを入力するとunhashed keyを聞かれる。main_ambushでも先程と同じ値(861836f13e3d627dfa375bdb8389214e)がハードコードされていて、これと入力した文字列のMD5ハッシュ値が比較されていることが分かる。
ハードコードされている値"861836f13e3d627dfa375bdb8389214e"をGoogleで検索すると"goldfish"のMD5ハッシュ値であることが分かる。
root@DESKTOP-G3LRDHC:~# nc mercury.picoctf.net 4052 Enter Password: reverseengineericanbarelyforward ========================================= This challenge is interrupted by psociety What is the unhashed key? goldfish Flag is: picoCTF{p1kap1ka_p1c09a4dd7f3}
Flag : picoCTF{p1kap1ka_p1c09a4dd7f3}