WarGAME/dreamhack.io

[dreamhack.io | pwnable level 1] basic_exploitation_000, basic_exploitation_001,

ruruby 2021. 5. 31. 18:10

1. basic_exploitation_000

128만큼의 버퍼를 할당하고, buf의 주소를 알려구조, scanf로 buf에 값을 읽어들인다.
flag를 어떻게 읽을 수 있는것일까... 참고한 내용은 Return Address Overwrite이라는데, 문제는 어디로 return address를 지정해줘야하는지를 모르겠다는 것이다.
buf에 읽어들이는 값으로 메모리에 cat ./flag를 실행하는 쉘코드를 넣으면 되는 것일까?

%p:  변수의 주소를 헥사로 표현

도저히 모르겠어서 구글링해보니, 공통적으로 사용하는 쉘코드가 있는 것 같아서 이 쉘코드를 실행하도록 코드를 작성했다.
(buf 배열의 시작 지점을 기준으로 볼 때) main을 보면 ret에 있는 스택의 위치는 buf배열의 공간인 128(0x80)에 sfp 4bytes를 더한 값인 132bytes를 더한 값이다.

26bytes의 쉘코드 + 106bytes의 dummy코드(132bytes-쉘코드의 bytes) + return 주소값(접속 시 받은 주소로 지정) 이 총 payload이다. 접속해서 작성한 payload를 입력해주니 flag가 출력되었다.

2. basic_exploitation_001

read_flag() 를 호출해야 하는데, main함수에 해당 함수를 호출하는 코드가 없다.

오랜 시간동안 입력해주지 않으면 "TIME OUT"이 출력되고, 아무 값이나 입력해주어도 바로 프로그램이 종료된다. 모르겠으니 실행파일을 gdb로 열어보자.

우선 main에서 gets부분을 실행할때 입력하는 값으로 공격해야할 것 같아서 실행해보았다.(여기서 한참 고민.....진짜 감이 안왔음.main에서 gets로 값을 저장해도 이후에 함수를 실행하는 부분이 없는데 어떻게 해야하는 것인지 전혀 모르겠었다.)

gets로 return지점의 주소를 readflag의 주소로 지정해주면 될 것 같다.
ret하기 직전의 esp에 저장된 값이 0xf7e16647이므로 이 주소값이 정상적인 return 주소값이다. 중요한 건 ret하기 직전의 esp이 가리키는 스택의 주소값인데, 이건 0xffffce0c이다. 따라서 이 지점에 read_flag()의 시작 지점의 주소를 저장해주면 될 것 같다. gets를 통한 오버플로우로 설정해주면 될 것 같다.

read_flag함수의 시작 주소는 0x080485b9이다. 리틀엔디안 방식으로 들어가니까 \xb9\x85\x04\x08 로 넣어주면 될 것 같다.

no pie니까 주소가 계속 바뀌는 것도 아닌 것 같은데....

계산해보면,
일단 dummy값은 0xffffce0c-0xffffcd88로 132이다.

payload에 해당 값을 넣어서 보내주면 될 것 같다.


와..,.성공....리얼 라업 안봤다.

3. sint

소스코드를 보면 int 형 변수에 값을 받은 뒤, 이 값이 허용범위 내에 있을 때에만 해당 사이즈-1만큼 buf배열에 값을 입력받는 것이다.
size변수(int형 변수)에서 버퍼 오버플로우 발생시키고, buf에서도 버퍼 오버플로우를 발생 시켜서 return지점이 저장되는 지점에 get_shell()시작 지점을 저장해주면 될 것 같다.
1. size변수에서 오버플로우 발생시키기가 아니고, read에서 size-1만큼 읽으니까 size에 0을 넣어주면 된다.

스택 내 buf의 시작지점을 확인해보면 입력으로 넣어주었던 aaaaaa가 확인되었다.

ret직전의 스택을 보면 0xffffce32지점에 ret할 주소값이 저장되어있음을 알 수 있었다.

ret할 주소값이 저장되는 지점-buf의 시작지점을 빼주면 dummy코드의 양이 나온다.


260개의 dummy코드와 get_shall()의 시작주소(리틀 앤디안 방식으로)를 넣어주면 될 것 같다.



위의 코드를 더 잘 짜는 방법도 있었다.