정수형 변수를 선언하고 -100을 대입하여 출력하는 프로그램을 작성하라.



 [Copy]
-100


#include <stdio.h>

void main()

{

int a = -100;

printf("%d" , a);

return 0;

}

a를 선언함과 동시에 -100을 대입한 후 출력하였다

'c언어' 카테고리의 다른 글

정보 올림피아드 - 512  (0) 2016.07.12
정보 올리미아드 - 510  (0) 2016.07.12
정보 올림피아드 - 105  (0) 2016.07.12
정보 올림피아드 - 104  (0) 2016.07.12
정보올림피아드 -103  (0) 2016.07.12



다음 출력 예와 같이 모든 단어를 15칸씩 오른쪽에 맞추어 출력되는 프로그램을 작성하시오.



 [Copy]
          Seoul     10,312,545        +91,375
          Pusan      3,567,910         +5,868
        Incheon      2,758,296        +64,888
          Daegu      2,511,676        +17,230
        Gwangju      1,454,636        +29,774


#include <stdio.h>

void main()

{

 printf("%15s%15s%15s\n","Seoul","10,312,545","+91,375");

 printf("%15s%15s%15s\n","Pusan","3,567,910","+5,868");

 printf("%15s%15s%15s\n","Incheon","2,758,296","+64,888");

 printf("%15s%15s%15s\n","Daegu","2,511,676","+17,230");

 printf("%15s%15s%15s\n","Gwangju","1,454,636","+29,774");

 return 0;

}


줄을 띄기 위하여 3번째 부분에만 \n을 사용했습니다 

'c언어' 카테고리의 다른 글

정보 올림피아드 - 512  (0) 2016.07.12
정보 올리미아드 - 510  (0) 2016.07.12
정보 올림피아드 - 509  (0) 2016.07.12
정보 올림피아드 - 104  (0) 2016.07.12
정보올림피아드 -103  (0) 2016.07.12


다음 출력 예와 같이 출력되는 프로그램을 작성하시오.

합계와 평균은 수식을 이용하세요. 



 [Copy]
국어 90
수학 80
영어 100
합계 270
평균 90


#include <stdio.h>

int main()

{

 int a,b,c,d,e;

 a = 90; b = 80 ; c = 100;

 d = a+b+c;

 e = d/3;

 printf("국어 %d\n",a);

 printf("수학 %d\n",b);

 printf("영어 %d\n",c);

 printf("합계 %d\n",d);

 printf("평균 %d\n",e);


 return 0;

}


수식을 이용하여 풀기 위하여 변수들을 만든뒤에 값을 넣어줬따 

합계와 평균이 정상적으로 나오게 하기 위해서 국어 수학 영어인 a , b , c 의 값을 

먼저 선언해주고 합계 평균을 만들어준뒤 출력하였다 

'c언어' 카테고리의 다른 글

정보 올림피아드 - 512  (0) 2016.07.12
정보 올리미아드 - 510  (0) 2016.07.12
정보 올림피아드 - 509  (0) 2016.07.12
정보 올림피아드 - 105  (0) 2016.07.12
정보올림피아드 -103  (0) 2016.07.12



다음 출력 예와 같이 출력되는 프로그램을 작성하시오.



 [Copy]
TTTTTTTTTT
TTTTTTTTTT
    TT
    TT
    TT


#include <stdio.h>

void main() {

printf("TTTTTTTTTT\n");

printf("TTTTTTTTTT\n");

printf("%6s\n","TT");

printf("%6s\n","TT");

printf("%6s\n","TT");

return 0;

}


%?s 를 이용하면 화면 왼쪽에서부터 원하는 자릿수(?) 만큼 출력한다 

본 문제에서는 TT가 띄어쓰기까지 포함해서 총 6자리를 가지고있으므로 오른쪽에서   6자리가 뛰어져 있어야 하기 때문에 %6s를 이용해서 풀었다

반대로 왼쪽 맞춤으로 하고 오른쪽에 빈 칸을 채우고 싶으면

printf("%-1s\n","TT");

TT_ 라는 결과가 나오게 된다 


본 문제에서는 T라는 문자를 출력해야했기 떄문에 " " 를 이용해서 TT를 묶어줬고

printf("%10d",123); 와 같은 경우는 큰 따옴표로 묶어주지 않아도 된다 


'c언어' 카테고리의 다른 글

정보 올림피아드 - 512  (0) 2016.07.12
정보 올리미아드 - 510  (0) 2016.07.12
정보 올림피아드 - 509  (0) 2016.07.12
정보 올림피아드 - 105  (0) 2016.07.12
정보 올림피아드 - 104  (0) 2016.07.12

FTZ - LEVEL19 를 chaining RTL 기법으로 풀어봤습니다

level19의 소스입니다! gets 함수가 잇으니 cat과 파이프를 이용해야겠군요


gdb를 분석해봤습니다 
<main+0> push ebp 
<main+1> mov ebp , esp
스택프레임을 설정해줬습니다
<main+3> sub esp , 0x28 
esp에 40만큼 빼줫습니다 (버퍼 40 선언)
<main+6> sub esp , 0xc
esp 에서 13만큼 뺴줬습니다 
<main+9> lea eax , [ebp-40]
eax에 ebp-40의 주소값을 넣어줬습니다
<main+12> push eax 
스택에 ebp-40을 넣어줬습니다
<main+13> call 0x80482f4 < gets > 
gets 함수를 호출해줬습니다
<main+18> add esp , 0x10
16만큼의 공간을  사용했습니다
<main+21> sub esp , 0x8
8만큼의 공간을 할당해줬습니다
<main+24> lea eax,[ebp-40] 
eax에 ebp-40의 주소를 넣어줬습니다
<main+27> push eax
eax를 스택에 넣어줬습니다
<main+28> push 0x80484d8
stdin을 넣습니다
<main+33> call 0x80483234 <printf>
printf 함수를 호출해줬습니다
<main+38> add esp , 0x10 
esp에 16을 더해줬습니다

RTL을 하기 위해서 System의 주소와 /bin/sh의 주소를 구해보겠습니다

/bin/sh의 주소도 구해보겠습니다

buf[40]+sfp[4]+&system[4]+exit[4]+/bin/sh[4]

쉘은 떳지만 id는 변하지 않아서 

RTL Chaining 을 이용해서 권한도 설정해줘보겠습니다

0x420d7920 = setreuid
3010 00000c1c 3009가 레벨19의 권한이므로 3010을 권한으로 넣어주겠습니다
setreuid(3010,3010)

그 후 setreuid의 인자값이 두개이므로 pop pop ret 하는 가젯의 주소를 구했습니다.


buf[40] + sfp[4] + &setreuid + &ppr + 3010 + 3010 + &system + dummy + &/bin/sh 
를 넣어줬습니다

정상적으로 level20의 권한을 휙득한 것을 확인할 수 있습니다

'해커스쿨 ftz' 카테고리의 다른 글

FTZ 정리  (0) 2016.05.22
FTZ-LEVEL20  (0) 2016.04.26
FTZ-LEVEL19  (0) 2016.04.25
FTZ-LEVEL18  (0) 2016.04.24
FTZ-LEVEL17  (0) 2016.04.24

ssh로 


fd@pwnable.kr port - 2222로 접속을 한 뒤 pw guest를 입력해주면



위와 같은 이쁜 친구를 만나볼 수 있다



목록들을 확인해보니 fd fd.c flag peda~ 가 존재하였고 flag는 실행 시 퍼미션 디나이드가 발생하는 상태이다.



fd.c를 열어봤더니 소스가 잇었다 . 

자 먼저 들어가기전에 중요한 핵심 함수들을 정리해보자 


atoi ( str ) = 문자열을 정수로 변환해줍니다 필요한 헤더는 stdlib.h 입니다.


read (a, b, c) = [ a = 데이터를 전송할 파일 디스크립터 b = 수신 한 데이터를 저장할 버퍼를 가리키는 포인터 c = 수신할 최대 바이트 수)


Strcmp(a , b)  = a 와 b 문자열을 비교합니다 


if 부분에 system("\bin\cat flag")를 호출해주네요 ! 저기 부분을 맞춰줘야지 풀 수 있는 문제라고 예상가능합니다 


헌데 argv[1]부분을 0x1234로 빼버리죠? 그렇다면 read함수에서 buf에 정상적으로 값을 전달 해 줄 수가 없으므로 


0x1234를 십진수로 변환한 4660을 넣어줘서 4660 - 4660 = 0으로 초기화 해줍니다.


그리고 strcmp 부분에서 LETMEWIN과 버퍼에 입력된 문자열이 동일하면 system함수가 열어지네요 


이렇게 답을 얻은것을 확인할 수 있습니다.

'pwnable.kr' 카테고리의 다른 글

random  (0) 2016.08.26
passcode  (0) 2016.08.26
flag  (0) 2016.08.26
bof  (0) 2016.08.26
collsion  (0) 2016.08.26

GOT overwrite 간단하게 연습 해보려고 합니다 


환경은 SENTOS 6.7이며 보호기법은 다 걸려있는상태입니다

(보호기법은 필요없지만요!)


scanf , printf 어느쪽이든 상관없습니다 .


둘의 plt주소를 발견 한 후에 system함수로 뒤바꿔버리고 

"%s" 대신에 "./a;" 가 실행되게 하여 

root 권한이 걸린 파일을 실행시켜보겠습니다 


먼저 scanf 혹은 printf의 plt 주소를 찾아보겠습니다 



readelf -S 명령어를 통해 plt의 주소를 찾았습니다 . 


그 뒤 gdb를 열어서 plt의 주소들을 봐보니 


pintf 와 scanf 둘 다 보이는걸 확인할 수 있습니다 


그중에서도 printf로 진행해보겠습니다



먼저 system 주소를 구했습니다 


이제 %s의 주소를 구해야겠지요 ? 



0x8048514를 이동시켜주네요 



확인해봤더니 %s가 존재합니다 


이 %s를 어떻게 a로 돌려서 공격하냐 ? 

16진수로 주소값이 써주는상태고 SET으로 변경만 하면 되니까 



./a; 를 만들어 줘야하니 . = 0x2e   / = 0x2f   a = 0x61  ; = 0x3b    

리틀 엔디언으로 ./a; 는 0x3b612f2e 가 되겠습니다 


그렇다면 이제 print plt에 system 주소를 주고 
%s에 ./a;를 줘보겠습니다 



이런식으로 실행이 되네요! 재밌습니다 

'시스템' 카테고리의 다른 글

Loaded plugins : fastestmirror 에러  (0) 2016.06.01
cent os gdb 설치  (0) 2016.05.29
Cent os 에서 xshell , putty 연동  (0) 2016.05.29
cent os 컴파일러(gcc) 다운  (0) 2016.05.28
함수 호출 규약(Calling Convention)  (0) 2016.05.27

ROP - 콜 스택을 제어 하여 리턴 명령어가 실행되기 이전에 프로그램 안에 존재하는 실행 가능한 메모리 영역에서 명령어들을 추출하여 DEP,ASLR같은 기법들을 우회하여 공격할 수 있습니다!


알아야 하는 기본 지식으로는 plt 와 got를 이용하면 got overwriter 와

RTL Chain을 알아야합니다 . 


RTL Chain을 다시 한번 아주 간단하게 알아보고 가겠습니다



RTL Chain이란 그냥 말 그대로 RET를 연속적으로 호출하여 원하는 함수들을 계속 사용해버리는 느낌입니다!


사진을 보시면 RET1~4까지 화살표들이 귀엽게 있습니다.


그중에서 RET2에서 RET3으로 가는 스택안으로 들어가본건데요 

RET2에 POP POP RET가젯을 넣음으로써 POP POP (Parameter1 , 2)에 원하는 실행 함수를 넣고 RET부분에 RET3으로 가게만듬으로써 RET가 계속 일어나게 합니다 .


간단한 예시와 설명을 보면서 진행해보겠습니다 


(*FTZ - LEVEL11을 사용했습니다)



환경변수를 이용한 GOT Overwrite도 다음에 해봐야겠군요!


먼저 ROP를 간단하게 말씀드리자면 버퍼오버플로우 약점이 잇는 함수의 (해당 소스에서는 strcpy) 인자 값만큼 pop하고 ret 구조를 가진 가젯을 찾은 후 공격하기 위한 가젯들의 주소를 하나하나 구해서 페이로드를 짠 뒤 RTL Chain 을 사용해 시스템함수 같은 것을 실행하여 공격합니다 


본 소스로 예제를 보여드리겠습니다 



먼저 gdb분석을 통해 strcpy@plt = 0x804835c를 구했습니다 .



system = 0x4203f2c0 &system 의 주소도 구했습니다 .


strcpy의 안자가 두개기 때문에 pop pop ret 하는 가젯도 구했습니다 .

0x80484ed



여기서 readelf -s 을 사용해서 bss의 주소를 알아야합니다 .


왜 굳이 bss 영역을 사용해야하냐 ? 

bss영역은 한마디로 주소값이 변하지 않습니다 .


bss의 주소는 0804963c 인것을 확인했습니다 .


이제 대강 필요한 정보들을 수집했으니 가젯들을 모아서 

 /bin/sh를 만들어봅시다 .

어렵게 생각하실 필요 없습니다 .

/   ,  b  ,  i  ,  n  , /  , s  , h  문자가 총 몇개지요 ? 

중복되는 문자 / 를 하나 빼면 6개입니다 .

간단합니다 .6개의 주소를 구하면됩니다 .



objdump -s [대상] | grep [원하는 가젯 단어] --color=auto (--color = auto를 사용한 이유는 원하는 가젯 단어에 색깔을 입혀서 구분이 쉽게 만들기 위함입니다.)


자 그러면 저기서 b를 발견했습니다 그래서 b의 주소가 뭐냐?


맨 왼쪽을 보시면 80480f4 라고 써있습니다 . 저 주소는 / 의 주소임을 짐작할 수 있습니다 .


/ = 80480f4 일단 하나를 구했습니다 . 


자 근데 여기서 b의 주소는 /lib/ld ~ 이러한식으로 구성이 되어있는데 

/ = 80480f4 이고 l = 80480f5 i = 80480f6 입니다 


그렇다면? b = 80480f7 입니다 . i 도 구해버렸네요!  i = 80480f6




n = 8048232 



s = 8048240 



h= 8048380


자 모든  친구들이 구해졌습니다! 


이렇게 퍼즐 조각 맞추듯이 가젯들을 모아서 단어를 만들어 공격하는것이 rop입니다.


자 이제 어떻게 페이로드를 짜느냐 ? C라던가 평소와 같이 16진수로 공격하기엔 어어어엄청 복잡하고 길어지더라고요 


그래서 파이썬으로 작성을 해봤습니다



struct 와 os 를 사용한 이유는


struct.pack('<I',number) 부분의 뜻은 리틀엔디안으로 정리한다는 소리입니다.

os.execv(TARGET,("",payload)) 를 사용한 이유는 

execv함수의 원형은 execv(path , argv[]) 입니다 .

path에 지정한 경로명에 있는 파일을 실행하고 argv를 인자로 전달합니다 .

그래서 os.execv(TARGET,("",payload)) 에서 TARGET은 공격할 위치로 만들어주었고 

뒤에 ("",payload) 를 사용한 이유는 (payload) 이렇게만 사용을 하면 파일명에 payload가 들어가서 에러가 난다 



두개 이상이 필요하다고 하면서 에러가 뜨는거같네요 

근데 TARGET 으로 이미 공격할곳을 넣어줬음으로 " "으로 공백으로 전달을 해주고 

argv[1]은 payload를 전달해줌으로써 공격을 합니다! 



이러한식으로 공격이 성립됩니다! 


아직까지는 ROP를 막을 확실한 방법이 없다고 알고 있습니다 .

열심히 공부하고 응용하면 효과적으로 사용할 수 있을거같네요!


'시스템 기법 정리' 카테고리의 다른 글

Fake EBP  (0) 2016.06.02
PLT , GOT [상세히] ,GOT Overwrite  (0) 2016.06.02
Format String Attack (FSB)  (0) 2016.05.30
ASLR를 해제하는 여러가지 방법  (0) 2016.05.29
plt , got , rtl chain , ASLR  (0) 2016.05.28

Fake EBP 란 ? Leave / RET 을 사용하여 ebp를 원하는 위치로 옮긴뒤에 공격자가 원하는 RET를 얻어내는 공격이다!


(*이 기법은 RET까지만 덮어쓸 수 있는 상태이고 RET에 스택과 라이브러리 주소등을 못넣도록 막아놨을때 사용하는 방법이다)

위에도 언급했지만 Leave / RET 이 중요하다!




Leave 와 Ret 의 역할입니다!




오버플로우가 일어나지 않은 상태의 스택입니다 


자 Fake Ebp의 공격방법이 무엇이냐 sfp에 buf+4 부분(쉘코드의 주소)을 덮어줍니다.


*여기서 sfp의 의미란? Sfp는 ebp가 복귀되는 주소를 저장하는 역할입니다!

Sfp에 buf-4값을 넣어줌으로써 ebp가 buf-4로 가게 해줘서 buf에 저장한 쉘코드가 온전하게 실행될 수 있도록 해주는 역할을 합니다


그리고 ret에 ret를 덮어줍니다 . 


그렇게 되면 


1차 -  Leave = Mov esp , ebp pop ebp 수행 esp에 ebp가 들어갑니다(esp = ebp)

그 뒤에 pop ebp 때문에 ebp가 스택에서 뽑혀서 buf-4로 갑니다  ..

방금 한 pop ebp 과정에서 pop 명령어 때문에 +4가 되므로 buf+4를 sfp에 넣어주는것입니다

그 뒤 ret 이 실행되는데 ret 에는 ret을 넣어놨기 떄문에 ret이 다시 실행됩니다 


2차 - Leave = Mov esp ,ebp pop ebp 를 다시 수행합니다 . 아까와 같이 esp에 ebp가 들어갑니다 .근데 현재 ebp의 위치는 어디죠? 바로 맨 아래입니다

그 뒤에 pop ebp로 ebp는 어딘가로 숑 사라져버리고 pop 명령어를 수행했기 때문에 +4가 됩니다. 그렇다면 esp는 쉘코드를 가리키게 되고 ret 수행으로 eip 명령으로 쉘 코드가 실행됩니다 .


1차 Leave = Mov esp , ebp pop ebp 에 대한 그림입니다 



Leave Mov esp , ebp 에서 buf 어딘가에 존재하던 esp가 Mov esp ebp 라는 명령어에 의해서 Sfp(&Buf-4)를 가리키고 있던 ebp와 같은 곳에 존재하게됩니다 .

그 뒤에 pop ebp 명령어가 실행이 되면서 sfp에 들어있던 buf-4로 ebp는 이동하게 되고 esp는 Leave/Ret을 가리키고 있는 상태가 됩니다 



pop eip 명령에 의해서 leave - ret의 주소를 가지게 되었고 jmp eip를 함으로써 

다시 한번 leave-ret을 진행합니다



2차 leave - ret이 진행됐습니다. 

leave mov esp , ebp가 진행됨으로써 아까 buf-4부분을 ebp가 가리키고 있기때문에 esp도 마찬가지로 똑같은 위치에 있게됩니다. 그리고 pop ebp를 수행함으로써 esp는 shellcode를 가리키게되고 ebp는 신경안쓰셔도됩니다


그 후에 ret 이 진행이 됩니다 현재 esp가 Shellcode를 가리키고 있는 상태기 때문에 eip 도 Shellcode를 가리키게 되고 pop eip를 함으로써 eip의 &Shellcode가 들어가게됩니다. 

그 후에 jmp eip로 쉘코드가 실행이됩니다 .


LOB - ZOMIBE_ASSASSIN 은 FAKE EBP를 통해서 푸는 문제입니다! 직접 해보고 싶으신 분은 참고 하시길 바랄게요!


'시스템 기법 정리' 카테고리의 다른 글

ROP  (0) 2016.06.06
PLT , GOT [상세히] ,GOT Overwrite  (0) 2016.06.02
Format String Attack (FSB)  (0) 2016.05.30
ASLR를 해제하는 여러가지 방법  (0) 2016.05.29
plt , got , rtl chain , ASLR  (0) 2016.05.28

PLT : 외부 프로시저를 연결해주는 테이블 , PLT를 통해 다른 라이브러리에 있는 프로시저를 호출해 사용할 수 있다.
[어떤 프로시저(함수들)이 있는지 나열되어있는 테이블]

 

GOT : PLT가 참조하는 테이블 프로시저들의 주소가 들어있다.

[실제 함수들의 주소가 들어있는 테이블]

 

PLT 와 GOT의 대략적인 개념을 말씀드리겠습니다.

 

함수를 호출하면(PLT를 호출하면) GOT로 점프하는데 GOT에는 함수의 실제 주소가 쓰여있습니다

첫 번째 호출에는 GOT는 함수의 주소를 가지고 있지 않으나 "어떠한 과정"을 거쳐서 주소를 알아내게 되고 

두 번째 호출 부터는 첫 번째 호출 때 알아낸 주소로 바로 점프합니다 .

 

어떠한 과정이란? 대략 과정만 말씀드리자면 

 

 

Static Link 와 Dynamic Link

PLT와 GOT에 대해서 조금 더 깊게 들어가 보기 위해서는 링커에 관해서 알아야합니다 

 

소스파일을 실행파일로 만들어 주기 위해서는 컴파일이라는 과정이 필요합니다.

아래는 간단한 컴파일 과정입니다(*출처 http://blog.eairship.kr/2)

자 여기서 만약에 작성한 소스 안에 printf 함수를 호출하는 코드가 존재하고 

include<stdio.h>와 같은 헤더 파일에는 printf의 선언이 잇다고 가정합니다

이런식으로 컴파일을 통해 오브젝트 파일이 생성됩니다 . 

하지만 오브젝트 파일만으로는 실행이 가능하지 않습니다 그 이유는 printf의 구현 코드를 모르기 때문입니다 . printf를 호출 했을 때 어떠한 코드를 실행해야 하는지 우리가 작성한 코드만 가지고서는 아직 아무것도 알 수 없습니다

 

오브젝트 파일을 실행 가능하게 만들기 위해서는 printf의 실행 코드를 찾아서 오브젝트 파일과 연결 시켜야 합니다.

printf의 실행 코드는 printf의 구현 코드를 컴파일한 오브젝트 파일로 연결 해야합니다.

이런 오브젝트 파일들이 모여있는 곳을 라이브러리(Library)라고 합니다.

 

이렇게 라이브러리와 같이 필요한 오브젝트 파일들을 연결시키는 과정을 링킹이라고 합니다 

 

이렇게 링킹을 하는 방법은 Static과  Dynamic 방식이 존재합니다 

Static Link 방식을 통한 실행파일 생성입니다 . 

 

Static Link 방식은 파일 생성시 라이브러리 내용을 포함한 실행 파일을 만듭니다

 

Static Link로 파일을 만들던 도중에

 

/usr/bin/ld : cannot find -lc 라는 에러가 나왔습니다.

 

collect2 : ld returned 1 exit status 라는 오류 같은 경우에는 lob golem 편에서도 언급을 햇었는데요 라이브러리가 정의가 되어있지 않아서 발생한 오류였습니다.

 

그렇다면 이번에도 마찬가지로 라이브러리가 문제란것을 짐작할 수 있습니다.

 

--------------------------------틀린 방법입니다 참고만 하세요 --------------------------

 

-l 뒤에 있는 문자가 검색되지 않은 라이브러리입니다! 

그렇다면 해당되는 라이브러리를 검색해보겠습니다

 

 

yum list | grep *문제되는 라이브러리명*lib (여기서는 lc 이므로 clib) 을 검색해줬더니 두 친구들이 검색되네요!

 

 

이러한 식으로 설치를 진행하겠습니다!  

 

--------------------------------------------------------------------------------------------------

 

 

해당 명령어를 사용함으로써  

 

성공하였습니다 -static 컴파일이 됐군요! 

 

Static 옵션을 사용하면 Statick Link 방식으로 컴파일이 됩니다.

 

실행 파일 안에 모든 코드가 포함 되어서 라이브러리 연동 과정이 따로 필요 없으며 한 번 생성한 파일에 대해서는 필요한 라이브러리를 따로 관리하지 않아도 되기 때문에 간편합니다. 

 

하지만 단점으로써는 파일 크기가 커지고 동일한 라이브러리를 사용하더라도 해당 라이브러리를 사용하는 모든 프로그램들은 라이브러리의 내용을 메모리에 매핑 시켜야 된다는 것이 있습니다.(매핑 - 연결 시킨다는 느낌으로 아시면 될거같습니다 )



† Dynamic linking

Dynamic Link 방식은 공유라이브러리를 사용합니다.
라이브러리를 하나의 메모리 공간에 매핑한뒤에 여러 프로그램에서 공유하여 사용합니다.

실행파일 안에 라이브러리 코드를 포함하지 않아도 되므로 Static Link 방식을 사용해 컴파일 했을때보다 파일 크기가 훨씬 작아지고 적은 메모리를 차지하며 라이브러리를 따로 업데이트 할 수도 있는것이 장점입니다 .

하지만 단점으로썬 실행파일이 라이브러리에 의존해야 하기 때문에 라이브러리가 없으면 실행할 수 없다는 점 입니다.



아무런 옵션을 주지 않은채 gcc 컴파일을 한다면 자동으로 Dynamic Link방식으로 컴파일이 됩니다.


이제 여기서 공부하려고 했던 PLT 와 GOT를 Dynamic Link 컴파일에서 사용합니다.


그 이유는 Static Link 방식으로 컴파일 시 라이브러리가 프로그램 내부에 존재하기 때문에 함수의 주소를 알아오는 과정이 따로 필요하지 않지만 Dynamic Link 방식으로 컴파일을 하면 라이브러리가 프로그램 외부에 존재하기 때문에 함수의 주소를 알아오는 과정이 필요합니다 .


Dynamic Link 방식으로 프로그램이 컴파일 된다면 함수를 호출 할 때 PLT를 먼저 첫번째로 참조합니다. 

그 뒤에 PLT 에서 GOT로 점프를 하는데 GOT에 라이브러리에 존재 하는 실제 함수의 주소가 쓰여있어서 이 함수를 호출하게 됩니다 . 


이것은 첫 번째 호출이고 첫 번째 호출에는 GOT에 실제 함수의 주소가 쓰여있지 않으나 두 번째 호출부터는 GOT에 실제 함수의 주소가 쓰여있습니다.


그래서 첫 번째 호출에는 Linker가 dl_resolve라는 함수를 사용해서 필요한 함수의 주소를 알아오고 GOT에 그 주소를 써준 후 해당 함수를 호출하게됩니다.


Dynamic link 방식으로 컴파일 된 프로그램입니다 .


시작하기 전의 printf 의 주소를 봤더니 printf@plt 라는 이름과 함께 0x80482f4를 가르키고 있습니다 .

하지만 시작 한 후에 printf의 주소를 다시 보니 plt라는 이름이 사라진 후 다른 주소로 변한 것을 볼 수 있습니다. 


Static link 방식으로 컴파일 된 프로그램입니다 

프로그램 시작과 시작 전의 주소가 같은 것을 확인 할 수 있습니다 .


자 근데 Dynamic link 방식으로 만들어진 프로그램에서는 GOT에 실제주소가 존재하는것을 알게됬습니다. 

근데 이 GOT 주소를 해커가 원하는 흐름으로 갈 수 있는 함수의 주소로 바꿔버린다면? 쉘을 실행시키는거도 가능하겠지요 ? 

이러한 기법이 GOT_Overwrite 입니다 . 


간단한 예제를 보여드리겠습니다!



printf 라는 함수가 있지요 ? 이 printf를 system으로 바꿈으로써 쉘을 실행시켜볼겁니다! ( 쉘 대신 youngzzang을 넣었엇지만 결과를 보여드릴수가 없어서 바꿧습니다-_-)




먼저 컴파일을 할 때 혹시나 있을 보호기법을 생각해서

gcc -o young young.c -z execstack -fno-stack-protector -m32 로 컴파일을 해서 

nx bit 보호 기법을 해제해줬습니다 [ young 대신에 파일명을 넣어주세요 ] 


readelf 명령어로 간단히 plt가 어떠한 주소에 있나 파악한 후에 

printf 의 0x80482f4를 타고 들어간 후에 printf@plt 에서 jmp 하는 *0x08049650부분을 system 함수의 주소로 set 해주어서 실행시켰습니다.

set &printf@got=&system 

그랬더니 쉘이 실행된것을 볼 수 있엇습니다!


참고 bpsecblog.wordpress.com/2016/03/09/about_got_plt_2/

      shayete.tistory.com/

      항상 두 블로그에서 많은것을 배우며 작성중입니다! 


'시스템 기법 정리' 카테고리의 다른 글

ROP  (0) 2016.06.06
Fake EBP  (0) 2016.06.02
Format String Attack (FSB)  (0) 2016.05.30
ASLR를 해제하는 여러가지 방법  (0) 2016.05.29
plt , got , rtl chain , ASLR  (0) 2016.05.28

+ Recent posts