old

System #1

nopdata 2016. 7. 8. 00:35

#1. GOT, PLT?
PLT(Procedure Linkage Talbe)

Procedure의 실제 호출 코드가 저장되어 있는 테이블. GOT를 참조하여 실제 함수의 주소 값을 호출한다.



GOT(Global Offset Table)

실제 함수의 주소를 가지고 있는 테이블. 처음부터 테이블에 실제 함수주소를 가지고 있지 않고 내부 동작을 통해 테이블에 실제 함수 주소가 삽입되는 동작을 수행한다.


http://training.nshc.net:8080/KOR/Document/[KOR-121205]_Linux_Format_String.pdf


#2. Study_2 풀이


● 왜 -1을 넣으면 뚫리는가?


취약점이 존재하는 vuln 함수 소스이다.

보면 get_n 함수로 (&nptr, 4u)를 매개변수로 받는다. 소스는 간단하게 getchar를 두번째 매개변수 만큼 nptr에서 읽어들인다.

처음에 get_n((int)&nptr, 4u)는 4자리를 getchar로 받아들이기 위함이다.

바로 아래 줄에서 atoi(&nptr)로 읽어들인 문자열을 숫자로 변환한다. 4자리를 받았으므로 양수로는 9999까지 가능한 것이다.

하지만 다음 조건을 보면 atoi로 변환한 v2값이 32보다 작아야 프로그램의 주요 기능이 동작한다.

이 if문을 우회해야 하는데 atoi는 양수 뿐만이 아니라 음수도 문자열을 숫자로 변환할 수 있다. 따라서 atoi("-1")을 하게 되면 -1이 리턴된다. 그렇게 되면 위에서 걸린 조건을 통과할 수 있다.

그 다음 호출되는 get_n에서 두번째 매개변수는 위에서 조건으로 사용한 -1이다. v2에는 -1이 들어있지만 get_n의 매개변수 타입을 보면 두 번째 매개변수는 unsigned int이다. 따라서 -1은 int로 나올 수 있는 최대의 수가 된다.


● RTL Chaining Local

got의 주소를 찾아 원하는 함수를 실행시켜야 한다. 그러기 위해서는 이미 알고 있는 사용되고 있는 함수의 got주소를 알아내서 원하는 함수를 실행시키면 된다.

단, 모든 시스템에서 함수간 주소 위치가 동일한 것이 아니므로 2개의 함수의 got 주소를 비교하여 라이브러리를 찾아야 한다.


< study_2 기본 형태 >

study_2의 기본 틀이다. nptr버퍼가 44bytes(0x2c)만큼 할당되어 있다. RTL Chaining을 하기 위해서는 Ret를 print 주소로 변경하고 함수의 got주소를 출력해야 한다. 그렇게 하기 위해서는 %x, %s 서식문자를 가지는 문자열을 출력해야 한다.

여기서는 "You said: %s" 를 사용하였다.


< study_2 RTL Chaining >

inp : perl -e 'print "-1aaaaA*48"+"\x70\x83\x04\x08\(print@plt) \x4e\x86\x04\x08(POPx2) \xf8\x86\x04\x08(you said...) \x0c\a0\x04\x08(print@got_adr) \x70\x83\x04\x08(print@plt) \x4e\x86\x04\x08(POPx2) \xf8\x86\x04\x08(you said...) \x18\xa0\x04\x08(libc@got_adr) \x2f\x85\x04\x08(vuln_adr)

먼저 -1aaa를 넣는 이유는 두 번의 get_n 호출이 있는데 먼저 4문자를 받아들이기 때문에 그 부분을 처리하기 위해서이다.

nptr 버퍼와 SFP까지 쓰래기 값으로 덮어 씌우고 리턴주소를 printf 함수로 지정한다. plt주소는 이미 나와 있으므로 gdb, ida로 찾으면 된다. 함수 호출 후 pop을 두번 해주어야 하는데 그 이유는 printf의 인자값으로 들어가는 2개의 값을 꺼내 줘야 하기 때문이다.

그렇지 않으면 printf 함수 이후 arg1이 다음 호출 대상이 되는데 이는 함수가 아니므로 원하는 대로 동작을 하지 않는다.

vuln 루틴을 한번 끝내고 나면 printf@got와 libc@got를 얻을 수 있다.

이 두 값을 기반으로 libc_base를 알아낼 수 있다.

< got 주소 >


printf@got, __libc_start_main@got의 주소를 가지고 libdb.com에 대입하여 해당하는 라이브러리를 찾으면 다음과 같다.

< libdb.com 대입 >

해당 주소를 넣으면 왼쪽과 같이 라이브러리를 찾을 수 있고 오른쪽 그림에서 처럼 원하는 함수의 libc_base+상대주소를 알 수 있다.


< system 함수 삽입 >

찾아낸 libc_base를 기반으로 system@got를 알아내 위 그림의 형태처럼 삽입을 하면 쉘을 얻어낼 수 있다.

< source code >

소스를 조금 수정하여 처음 시작 시 매개변수 1개를 입력 하면 그 매개변수를 이행하도록 하였다. default는 id이다.


< output >




#3. Socat 설치 및 리모트 exploit

< remote 실행 >

serv : socat tcp-listen:9000,fork,reuseaddr exec:./study_2

socat을 이용하여 프로그램을 서버로 만들어 놓고 클라이언트는 process였던 객체를 remote로 바꾸어 주고 send마다 recv를 해주는 식으로 소스를 조금 변경하면 된다.





'old' 카테고리의 다른 글

Pwnable.kr / uaf  (0) 2016.07.21
포포포포렌식 #3  (0) 2016.07.12
포포포포렌식 #3  (0) 2016.07.05
Suninatas / Forensic 39 (BR 복구)  (0) 2016.06.27
포포포포렌식 #2  (0) 2016.06.23