Skip to content

Latest commit

 

History

History
63 lines (47 loc) · 4.1 KB

PwnableWriteup.md

File metadata and controls

63 lines (47 loc) · 4.1 KB

bof

类型: 栈溢出, 覆盖关键值

writeup: 虽然有栈保护(canary), 但并不影响, 因为 canary 的校验是在函数结束时进行校验. 所以溢出 overflowmekey 即可.

gdb-peda$ disassemble func
Dump of assembler code for function func:
   0x8000062c <+0>:     push   ebp
   0x8000062d <+1>:     mov    ebp,esp
   0x8000062f <+3>:     sub    esp,0x48
   0x80000632 <+6>:     mov    eax,gs:0x14
   0x80000638 <+12>:    mov    DWORD PTR [ebp-0xc],eax
   0x8000063b <+15>:    xor    eax,eax
   0x8000063d <+17>:    mov    DWORD PTR [esp],0x8000078c
   0x80000644 <+24>:    call   0xb7e897e0 <puts>
   0x80000649 <+29>:    lea    eax,[ebp-0x2c]
   0x8000064c <+32>:    mov    DWORD PTR [esp],eax
   0x8000064f <+35>:    call   0xb7e88e60 <gets>
   0x80000654 <+40>:    cmp    DWORD PTR [ebp+0x8],0xcafebabe
   0x8000065b <+47>:    jne    0x8000066b <func+63>
   0x8000065d <+49>:    mov    DWORD PTR [esp],0x8000079b
   0x80000664 <+56>:    call   0xb7e64310 <system>
   0x80000669 <+61>:    jmp    0x80000677 <func+75>
   0x8000066b <+63>:    mov    DWORD PTR [esp],0x800007a3
   0x80000672 <+70>:    call   0xb7e897e0 <puts>
   0x80000677 <+75>:    mov    eax,DWORD PTR [ebp-0xc]
   0x8000067a <+78>:    xor    eax,DWORD PTR gs:0x14
   0x80000681 <+85>:    je     0x80000688 <func+92>
   0x80000683 <+87>:    call   0xb7f1fb00 <__stack_chk_fail>
   0x80000688 <+92>:    leave
   0x80000689 <+93>:    ret
End of assembler dump.

分析下就知道了, 计算下两个位置的差即可, 'A' * (0x2c+0x8) + '\xbe\ba\fe\ca'.

flag

类型: 栈内容缓存和变量未初始化导致任意地址写内容.

由于 passcode1 值未经过初始化, 因此使用之前栈内容, 并且之前栈内容可控, 导致 passcode1 的值可控.

并且由于 scanf("%d", passcode1);, 这句话并有写到 & passcode1 , 而写将值写到 passcode1 值的位置, 因为两点结合导致可写内容到任意位置.

直接修改 fflush.got.plt 的地址为条件成立地址即可.

uaf

类型: UAF 暂放

memcpy

movdqamovntps 指令执行, 地址必须 16-bytes 对齐.

因此要求 malloc 分配返回的地址必须是 16-bytes 对齐, 这需要了解 glibcptmalloc 的大致实现.

以下引用自 <glibc内存管理ptmalloc源代码分析.pdf> P16

为了使得 chunk 所占用的空间最小,ptmalloc 使用了空间复用,一个 chunk 或者正在 被使用,或者已经被 free 掉,所以 chunk 的中的一些域可以在使用状态和空闲状态表示不 同的意义,来达到空间复用的效果。以 32 位系统为例,空闲时,一个 chunk 中至少需要 4 个 size_t(4B)大小的空间,用来存储 prev_size,size,fd 和 bk (见上图),也就是 16B, chunk 的大小要对齐到 8B。当一个 chunk 处于使用状态时,它的下一个 chunk 的 prev_size 域肯定是无效的。所以实际上,这个空间也可以被当前 chunk 使用。这听起来有点不可思议, 但确实是合理空间复用的例子。故而实际上,一个使用中的 chunk 的大小的计算公式应该是: in_use_size = (用户请求大小+ 8 - 4 ) align to 8B,这里加 8 是因为需要存储 prev_size 和 size, 但又因为向下一个 chunk“借”了 4B,所以要减去 4。最后,因为空闲的 chunk 和使用中的 chunk 使用的是同一块空间。所以肯定要取其中最大者作为实际的分配空间。即最终的分配 空间 chunk_size = max(in_use_size, 16)。这就是当用户请求内存分配时,ptmalloc 实际需要 分配的内存大小,在后面的介绍中。如果不是特别指明的地方,指的都是这个经过转换的实 际需要分配的内存大小,而不是用户请求的内存分配大小。

intel指令文档

glibc内存管理ptmalloc源代码分析.pdf