ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Passcode Write-up
    표튜터와 함께하는 Pwnable/Pwnable.kr Write-up 2019.03.31 20:42


    Passcode... 갑자기 어려워졌다고 느꼈다.. 실제로도 푸는데 시간이 많이 걸렸다..



     코드를 보도록 하자

    많은 부분에서 입력을 받는데 일단 Bof가 일어날만한 부분은 없었다.

    또한 passcode1과 passcode2의 값에 조건을 걸어서 조건을 통과하면

    flag를 보여주는 형태이다. 한 가지 이상함을 느낀 부분은 바로

    scanf 함수이다. &가 없이 passcode1의 변수를 사용하고 있었다.

    아마 이 부분이 취약한 부분이 될 것 같았다.




    프로그램을 한 번 실행시켜 보았다.

    처음 name 값은 문자가 가능했지만 passcode1을 입력받을 때 숫자를 입력하니

    Segmentation fault가 발생했다. 쩝.. 



    그래서 이번에는 문자열을 입력해보았더니 그 다음 단계로 갈 수는 있지만

    Login Failed가 일어났다. 이러한 상황이 발생하는 이유는 바로

    scanf와 그 인자로 주는 변수에 있다. scanf 함수에서 포맷스트링이

     "%d"일 경우 정수형 포인터(변수의 주소값)를 인자로 넘겨야하는데

    코드에서는 정수형 변수를 넘겼기 때문에 이러한 일이 발생한다.



    모두가 알다시피 보통의 scanf 함수는 다음과 같이 사용한다.

     이런식으로 주소값을 넘기게되면 a의 주소값이 가리키고 있는 공간에 입력받은 값을 저장한다.




    하지만 위의 코드와 같이 변수를 직접 참조하게되면

    스택공간에 저장된 값을 주소값으로 사용하게되기 때문에

    잘못된 메모리 주소를 참조할 수 있으므로 Segmentation fault가 일어나게된다.

    ( Warning을 보게 되면 역시 Int *을 사용해야하는데 왜 int를 쓰냐고 말을 하고 있다. )




    이러한 scanf 함수 사용이 왜 문제가 되는지 조금 더 알아보도록 하자.

    gdb를 이용하여 오른쪽과 같은 코드를 어셈블리어 코드로 보게되면

    참조하는 방법이 다르다. 빨간색 상자에서는 ebp-0xc에 저장된 내부의 값 4Byte를 참조하는 반면,

    파란색상자의 경우 ebp-0x10의 주소값 자체를 참조한다. lea와 mov의 참조방식을 알아야한다.

    lea에서 [ ]일 때 주소값 자체를 참조하는 반면 mov의 경우 [ ]내부에 저장된 값을 참조하기 때문이다.

    그러므로 위에서 [ebp-0xc]의 경우 ebp-0xc의 내부의 값을 4byte(DWORD)만큼 참조하는 것이고

    lea eax, [ebp-0x10]의 경우 ebp-0x10의 주소값을 eax에 옮겨 eax에 저장된 주소값 자체를 참조하는 것이다.



    scanf 함수의 인자로 & 사용여부에 대한 차이는 바로 이러한 주소값 참조 방식이다!!

    이것이 문제가 되는 이유는 &를 사용하지 않은 경우, 내부의 값을 참조하는데

    만약 공격자가 입력가능한 공간과 참조하는 내부의 값이 저장된 공간이 겹치는 경우

    입력을 통해 값을 조작할 수 있다는 것이다. &를 사용하는 경우 주소값을 참조하기때문에

    겹치더라도 조작이 불가능하다. 그러므로 우리는 이점을 이용해야한다!!


    다시 문제로 돌아와서 gdb를 이용하여 어셈블리어 코드로 보도록 하자.



    < login >

    이 부분을 이용하여 공격을 진행하면 될 것 같다. welcome 함수에서

    입력할 수 있는 name 버퍼의 공간과 login 함수의 scanf 함수가 참조하는

    인자의 값의 공간이 겹치기 때문이다.



    < welcome >




    이를 확인하기 위해 name 값에 "a" * 100을 채워보았다.

    name버퍼의 96개 다음의 4byte가 login 함수의 scanf 인자로 넘어가고 있었다.

    위에서 설명한 사용자가 입력할 수 있는 공간의 값이 scanf의 함수 인자와

    겹치게 참조되는 경우다. 즉, 해당 4byte는 passcode1이 된다.


    scanf 인자인 [ebp-0x10] passcode1 4byte를 338150 = 0x0528E6으로 입력해보았다.

    우리가 만족시켜야하는 조건 중 passcode1은 통과할 수 있었다. 하지만 동시에

    만족시켜줘야하는 passcode2의 값은 passcode1 이후 주소인 [ebp-0xc]값 4byte 는데

    이 값은 Canary로 값으로 랜덤하게 변하며 ret를 변조할 수 없었고 입력 길이제한으로

    오버플로우도 할 수 없었기에 우리가 원하는 13371337로 덮어쓸 수 없었다

    그러므로 다른 방법이 필요했다.!!



    그 방법은 바로 겹치는 공간 즉, scanf 함수의 인자를 이용해서 Got Overwrite를 일으키는 것이다.

    이 방법을 이용하면 조건문을 굳이 통과할 필요가 없다. 해당 코드에서 이미 system 함수를 사용하고 있었고

    우리는 got 값도 쉽게 알아낼 수 있었다. name 버퍼에 값을 입력할 때 마지막 4byte를

    이용하여 login함수의 scanf의 인자로 넘겨줄 수 있었기 때문에 우리는 이 인자로 fflush의 got를

    넘겨줄 것이다. 그리고 입력값을 system 함수의 실제주소를 넘겨주게되면 fflush가 실행될 때 fflush가 아닌

    system함수가 실행될 것이다. (굳이 fflush가 아니여도 된다. Got Overwrite한 뒤에 나오는 함수면 가능하다.)

    하지만 system 함수에 사용될 인자값을 어떻게 넣지? 하는 고민이 생겼다.




    그러나 이미 코드에서 인자를 넣어준 상태이므로 system 함수의 plt가

    아닌 system함수에 인자를 넣어주는 부분의 주소 값을 넘겨주면 fflush함수가 실행될 때

     이 부분부터 동작하므로 flag값을 볼 수 있을 것이다.



    got값은 아주 쉽게 구할 수가 있었다.





    위에서의 설명대로 Payload를 구성해보았다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    from pwn import *
     
    = ssh("passcode","pwnable.kr",port=2222, password ="guest")
    = s.process("./passcode")
     
    fflush = 0x0804a004
    name = "a"*96
    name += p32(fflush)
    system = 134514147
     
    script = """
    b*0x08048665
    """
    #gdb.attach(p,script)
     
    p.recv(1024)
    p.sendline(name)
    p.recv(1024)
    p.sendline(str(system))
     
    p.interactive()
     
    cs




    여기서 system 함수의 주소를 10진수로 나타낸 이유는 scanf 함수가 인자를 받을 때 "%d"

    포맷스트링을 사용하기 때문이다. 그러므로 0x080485EA의 10진수인 134514147을 넣어주고

    Payload를 실행하게되면~~~




    Flag를 볼 수 있게 된다~~~~







    '표튜터와 함께하는 Pwnable > Pwnable.kr Write-up' 카테고리의 다른 글

    Mistake Write-up  (0) 2019.04.01
    Random Write-up  (0) 2019.04.01
    Passcode Write-up  (0) 2019.03.31
    Horcruxes -> Write-up  (0) 2019.03.29
    Flag Write-up  (0) 2019.03.28
    Bof Write-up  (0) 2019.03.26

    댓글 0

Designed by Tistory.