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}