이번 문제는 저번 문제에 비해서 코드가 상당히 짧아졌습니다 .
buffer가 40이 할당되어있는데 strncpy로 41만큼을 넣을 수 있습니다.

이번 문제도 고민하다가 결국 새로운 기법이 필요하다는걸 알고 화가낫는데요 

이번에 필요한 기법은 Frame Pointer Overflow 라는 기법이 필요합니다.
sfp를 1개만 버퍼오버플로우가 가능할때 사용할 수 있는 기법입니다 .

sfp는 이전 스택프레임의 포인터를 가리키고있는 친구입니다
Frame Pointer Overflow는 leave,ret을 이용한게 중요합니다 
leave 는 move ebp,esp /pop ebp를 수행하게됩니다 .
esp는 현재 스택의 가장 위의 포인터라고 생각할 수 있습니다.
여기서 mov ebp,esp를 하면 현재 스택의 가장 위의 포인터가 현재 스택의 가장 아래를 가리키고 있는 ebp에 들어갑니다 [ esp(sfp에 우리가 1개의 값을 넣은값이 포함되잇음) ]
그리고 이제 pop ebp를 수행함으로써 esp가 4가 증가하게 됩니다 .
(4가 증가한것을 계산하여 sfp를 이용해야합니다)
http://research.hackerschool.org/Datas/Research_Lecture/sfp.txt

이제 ret주소에다가 쉘코드의 시작주소를 넣어줌으로써 공격을 하게 됩니다 


problem_child를 이용해서 풀어야 하므로 problem_child를 gdb로 열어봤습니다 여기서 leave에 브레이크 포인트를 잡아준뒤 esp에서 100개를 뽑아줬습니다.



A가 버퍼 40 + sfp값 1추가한 총 41개가 들어가있습니다 .    

----------노트북에서 데스크탑으로 바꿔서 진행해서 주소값이 조금씩 달라졌습니다


쉘코드 25 + nop값 15  + sfp변경할 값 1 해서 총 41을 넣어줬더니 
세그먼트폴트가 떠서 코어덤프를 해서 찾아봤습니다 

이렇게 찾자니 가독성..?이 조금 떨어지는거같아서 단순히 A41개만 넣어줘서 다시 봐보겠습니다 

problem_child+41에 브레이크 포인트를 걸어준뒤에 

A를 단순히 41개 넣어줬습니다 .
아까 제가 찾앗던 주소값에서 조금 변경된것을 보여줄 수 있습니다 .
이제 저기서 찾은 주소값으로 공격을 할 수 있는데 단순히 +4를 넣어주는것이 아닙니다 ( 위에 올린 문서링크를 읽고 참고해주세요 )

 +4는 일단 leave,ret 하는 과정에서 pop을 할때 +4가됩니다.그 후에 단순히 +4만 해야하는것이 아니라 우리는 sfp값을 변조해서 쉘코드가 잇는곳을 실행시키도록 하는 공격을 사용하는것인데 buffer가 들어있는 주소 값 (+4)까지 생각을 해야 하므로 
공격하려는 주소에서 -8을 해서 공격을 해주면된다

94-8을 해줘서 8c로 공격을 하였더니 권한을 휙득할 수 잇었다 .


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

LOB giant  (0) 2016.05.12
LOB bugbear  (0) 2016.05.12
LOB golem  (0) 2016.05.10
LOB skeleton  (0) 2016.05.05
LOB vampire  (0) 2016.05.04


golem 의 소스입니다 
마지막 부분이 추가됫네요 

 // stack destroyer!

        memset(buffer, 0, 44);

memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48));

buffer부터 메모리 끝 영역까지 전부 초기화 해버려서 저번 문제에서 사용햇던 메모리 마지막 영역을 사용 할 수가 없게되었다.

고민하고 시도해보다가 알게 된 방법이 리눅스 공유 라이브러리에 대한 개념을 알아야한다 . (타 블로그와 위키에서 공부를 하였습니다.)
https://wiki.kldp.org/HOWTO/html/Program-Library-HOWTO/shared-libraries.html

LD_PRELOAD 

프로세스 실행 과정 중 라이브러리를 로딩 할때, LD_PRELOAD 변수가 설정되어 있으면 해당 변수에 지정된 라이브러리를 먼저 로딩하고, 이중 libc 함수명과 동일한 함수가 있다면 해당 함수를 먼저 호출해 준다.

즉, 자동으로 후킹을 수행하도록 해준다는 말과 같다.

0xff                                    ~                                      0x00
커널 | argv | argc | ret | ebp | buf | 공유라이브러리 | heap | data | code
      |---------  stack ----------------|

 메모리 구조는 이런식으로 구성이 되어있고 여지껏 stack을 이용해서 공격을 진행해왔습니다 .
그리고 이번 문제는 공유라이브러리 영역을 이용해서 공격을 해야합니다 .

원래 프로그램을 실행시키면 보통의 공유 라이브러리를 로드하지만
LD_PRELOAD를 정의할시 프로그램을 실행하면 LD_PRELOAD에서 정의해준 라이브러리를 로드하게되고 이번에는 저 공유라이브러리 영역에 데이터를 올려서 진행을 할것이다 .

공유 라이브러리 영역에 쉘 코드를 넣은뒤에 RET주소를 공유 라이브러리에 넣은 쉘코드의 주소로 덮어 씌워준다 
위키 3.4를 참고하여주세요 
gcc -fPIC -shared -o ./shellcode ./Empty_Test_Program.c
위키 3.5를 참고하여주세요 
export LD_PRELOAD=./shellcode
shell코드 주소를 확인 후 ret주소에 덮어쓴다 

이 정도가 순서가 되겠습니다 그럼 진행해볼게요 

진행을 하던 도중에
collect2 : ld returned 1 exit status 라는 오류가 떳네요 
이유를 생각해보니 직접 라이브러리 정의를 안해준거같습니다 .

라이브러리 정의 문제가 아니였고 생각해보니 공유 라이브러리도 하나의 심볼릭링크로 만들어주는 작업이기때문에 \x2f 가 제외된 48바이트 쉘코드를 이용해서 풀엇어야 했습니다 .


별다른 오류가 뜨지않는걸 확인했습니다
export를 이용해서 정상적으로 LD_PERLOAD에 올라가 있는지 확인해보겠습니다


정상적으로 등록된거같습니다 


환경변수에 등록한 이후에 gdb를 열려고하니 자꾸 저러한 에러가 떠서 gdb를 먼저 분석한 후에 환경변수를 등록하고 진행을 해보겠습니다 .


leave 부분에다가 브포를 잡고 진행을 해보겠습니다 


계속 ls:error in loading shared libraries 라는 에러가 뜨면서 진행을 계속 하지 못했습니다 찾고 찾고 찾고 또 찾아본후 가장 유력한 원인이 gdb버전이 낮아서 에러가 난거같다는 주장이 잇었습니다 분명히 bash2를 썻는데..하며 생각해보며 혹시나 하는 생각에 /bin/bash2 export SHELL =/bin/bash2도 사용해줬습니다 .

심볼릭링크도 지운 후 다시 만들엇더니 오류가 뜨지 않았습니다 ..

문제 진행할때 저 친구들을 입력하는것을 습관을 들여야겠습니다-_-;


공유 라이브러리는 낮은 주소에 잇다는걸 확인을 하여서
esp에서 -100부터 -200.. 점점점점 낮춰가며 노가다를 한 끝에 놉코드와 쉘코드 친구들을 발견했습니다 .정말 반가워요 

적당한 주소값을 고른 후 공격을 해보겠습니다 


심볼릭링크로 공격을 해줘야하나 아니면 다른 쉘코드를 추가로 써줘야하나 무엇을 먼저 시도해볼까 고민을하다가 저렇게 공격을 했더니 바로 쉘을 휙득했습니다
기법을 전혀 모르면 풀 수 없고 알아도 저런 어처구니없은 버전의 낮음이 가져온 폐해였습니다

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

LOB bugbear  (0) 2016.05.12
LOB darkknight  (0) 2016.05.11
LOB skeleton  (0) 2016.05.05
LOB vampire  (0) 2016.05.04
LOB troll  (0) 2016.05.04


이번 vampire 코드에는 새롭게 ultra argv hunter! 가 생겼네요 

for(i=0; i<saved_argc; i++)
                   memset(argv[i], 0, strlen(argv[i]));
i= 0이고 saved_argc보다 작을때까지 for문으로 반복을하는데 
argv[0]까지 사용 못하네요 그러면 이제는 도대체 어떻게 공격을 해야할까요 


스켈레톤을 tmp폴더로 옮긴 후 gdb로 열어봤습니다 .
몇시간을 끙끙 거리다가 도저히 안될거 같아서 지인에게 여쭤보고 찾은 기법
fake ebp입니다 
*먼저 fake ebp는 leave , ret을 이용합니다 
leave = move esp , ebp        ret   pop eip
           pob ebp                       jmp eip
ret 에서 eip에 leave의 주소를 넣어줌으로써 leave를 두번 실행한다
문제를 풀면서 예시와 함께 설명을 드리겠습니다 .

먼저 leave에 브레이크 포인트를 잡아주겠습니다 

먼저 A*40[버퍼] + BBBB [SFP] +CCC+\xbf [RET]



leave 말고 buffer의 주소를 찾기위해 strcpy 다음에 브레이크 포인트를 걸어줬습니다

버퍼에 A가 쌓여있는것을 확인할 수 있습니다 SFP와 RET도 보이는군요

------------------------------------------------------------------실패햇읍니다
(fake ebp로 푸는게 아님)



남아있는 값을 확인하기 위해서 48개만큼 bf로 채웠습니다 

0xbfffffec에 argv[0]에서 남아있는 값들이 남아 있는 것을 확인했습니다


argv[0] 값을 확인해보기 위해서 x/s로 하나하나 봤더니 지워지지 않은 argv[0]이 존재하였습니다 

심볼릭 링크를 이용하고 ../AABB 로 시작을 하기 때문에 +6을 해서 ee +6 을해서 
0xbffffff2를 argv[1] ret에 넣었습니다 


export SHELL =/bin/bash2 를 하면 gdb에서 bash2가 적용됩니다 


gdb에서 아까 처음에 심볼릭 주소 +6이 되있어서 argv[0]주소에 +6을 해준 값을 ret 주소에 넣어줬습니다  
세그멘테이션 폴트가 발생한것을 파악하고 0xbfffffa0 의 주소들을 한번 봐보기 위하여 x/100wx 로 봐줬습니다 . 0xbfffffc0 : ~ 0xeb424241 이 발견됬고 
0xbfffffc0 부터 4바이트씩 표현을 해주면서 파악해줬습니다


쉘코드가 시작되는 0xeb가 0xbfffffcb에서 확인되었고 얻은 cb를 이용해 놉*44+ret주소에 0xbfffffcb로 바꿔줘서 

eip = 현재 명령어를 확인하게 해주는 친구 를 사용해서 봐줬는데
연산결과가 스택끝값을 넘어가는것을 확인해서 세그폴이 발생하는것을 확인하였습니다.
그래서 a를 추가적으로 쉘코드 뒤에 추가적으로 써줘서 주소의 끝값에 닿지 않도록 하여서 공격을 하였습니다 


주소를 넣기 편하게 해주기 위해서 \x90 놉 코드를 50개 정도 넣어주었고 아까 말씀 드렸더건처럼 a를123개 그냥 무작위로 크게 넣어줘서 주소 끝값에 닿지 않도록 하였습니다 .


stack is still your friend 라는 문구가 뜨지않도록 그냥 \xbf를48번째에 넣어준후에 주소를 봐보니 a의 주소값들이 정상적으로 출력되고 있습니다 .


0xbfffff40에서 값을 봐주니 nop코드가 보이고 쉘코드가 보이는것을 확인할 수 있습니다 .




*번외 rm -rf `python -c 'print "\x90'`*
=\x90으로 시작하는 친구들을 모두 지워준다 

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

LOB darkknight  (0) 2016.05.11
LOB golem  (0) 2016.05.10
LOB vampire  (0) 2016.05.04
LOB troll  (0) 2016.05.04
LOB orge  (0) 2016.05.02


뭔가가 더 추가되서 등장할 줄 알았는데 
에그헌터라던가 그러한 친구들이 지워지고 새로 등장한 친구는
if(argv[1][46] == '\xff')
{
printf("but it's not forever\n");
exit(0);
}

argv[1] 의 [46] 부분이 \xff면 stack is your friend 라는 문구와 함께 종료가 되버리는군요.


모든 프로그램이 완료된 후를 보고싶어서 ret에 브레이크 포인트를 주었습니다.


그러니 아무리 진행을 해도 but it's not forever 이라는 문구와 함께 실패를하고 
코어파일을 아무리 분석해봐도 여러가지 다른 방법을 써봐도 ff를 벗어날 방법을 생각 못하고 있던 와중에 argv[2]에는 한도가 없지 않았나 ?
1000개를 넣어보자 하고 생각이 들었습니다.


값이 변하는게 느껴져서 

10000개를 넣어줬습니다


이대로 좀더 값을 주면 ff값도 넘어갈 수 있을거 같습니다


10만개를 넣어줬더니 드디어 ff에서 벗어나서 fe가 나오는군요 ..!

어차피 nop코드를 넣어줬기에 무시하고 쭈우우우욱 실행되므로 nop의 적당한 주소를 넣은 argv[1]의 리턴값에 넣어준 다음에 진행 해보겠습니다 


argv[1]에 필요없는값44개와 nop의 주소를 박아준뒤에
argv[2]에 놉 코드를 10만개 사용한뒤에 쉘코드를 넣어줌으로써 권한을 얻는것을 성공하였습니다 .

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

LOB golem  (0) 2016.05.10
LOB skeleton  (0) 2016.05.05
LOB troll  (0) 2016.05.04
LOB orge  (0) 2016.05.02
LOB darkelf  (0) 2016.05.02


[시작 이전에 이 문제를 푸는데는 2틀 정도를 사용했습니다. 제대로 정리는 아래에다 해놨으니 위에를 좀 읽어보시되 문제 풀이는 아래를 참고하시면 좋겠습니다]

새롭게 one more! 이라는 주석과 함께
memset (argv[1], 0, strlen(argv[1])); 이 추가됐습니다 

memset 이란? 다시 한번! memset(a,b,c) = a = 채울 메모리의 주소 b =채울 문자 c = 채우려고 하는 문자의 개수입니다! 
argv1에 0을 argv1 개수 만큼 채워버리네요 ? 으으으으으음.....
이번에는 argv[1]에 뭔갈 채워넣어도 0으로 다 대체를 해버리는군요 
\xbf를 어떻게 넣어야 할지 곰곰히 생각을 해봐야겠습니다 

argv[0]을 이용해야하는데 argv[0]은 파일명입니다 . 이 파일명을 이제 바꿔줘야하는데 사용되는 방법이 바로 심볼릭 링크입니다 . 
(아무리 해도 방법을 모르겠어서 지인에게 물어본 후 진행했습니다)

컴퓨팅에서 심볼릭 링크(symbolic link) 또는 기호화된 링크는 절대 경로 또는 상대 경로의 형태로 된 다른 파일이나 디렉터리에 대한 참조를 포함하고 있는 특별한 종류의 파일이다. -출처 위키 

ln - s 명령어로 심볼릭링크 파일을 만들 수 있으나 
단 \x2f가 있으면 만들 수 없으므로 \x2f가 없는 쉘코드를 사용해야합니다!
그래서 저는 48byte 쉘코드를 이용하기로 했습니다 

"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`

토나오게 저한텐 어려운 문제입니다 이틀 가까이 해매고있습니다 

심볼릭 링크가 글자가 깨져서 너무나도 해맸습니다 정말 진짜 생각할수록 성질나네요 

그래서 이렇게 AABB라는 값을 넣어줬습니다 . 
그 뒤에 자동 완성 기능을 이용해서 gdb를 실행시키는데 성공했습니다
농담안하고 너무 좋아서 숨을 헐떡였습니다 .

esp값이 strcpy인자로 들어가기 때문에 strcpy에 브레이크 포인트를 줬습니다


혹시나 이렇게 argv[1] [2] 를 불러서 풀 수 있을까 하고 알면서도 시도를 해봤지만 역시 argc must be two! 라는 문구가 뜨면서 짤리네요 


47 =! \xbf 를 만족시키지 못했더니 stack is stiil your friend. 라는 오류문구가 나오는군요 그럼 더 추가시켜보겠습니다.

argv[1]에만 값을 넣으니 정상적으로 실행이 되는군요



제가 넣은 쉘코드가 맞나? 의심되지만 그나마 의심가는거라도 노려서 공격코드를 작성해보겠습니다.


이런식으로 하니 또 오류가 발생하는군요 심볼릭 링크 화납니다 .

계속 시도하였으나 실패하여서 코어덤프 이용하기전에 다시 한번 분석해보기로 하였습니다.


이번엔 이 주소를 노려보겠습니다 .

----------------------------------------------------------------------------------------------------정리해서 다시 시작하겠습니다

bash2를 안한 상태에서 심볼릭 링크한 파일을 gdb로 열었습니다.
쉘코드가 중간에 깨져있는걸 보아하니 심볼릭 링크할때 제대로 되지 않았나 보군요.


ps명령어도 bash 상태인것을 확인해봤습니다.


심볼릭 링크를 지워버린후에 bash2를 해서 새롭게 심볼릭 링크를 만든 후에 gdb로 다시 한번 분석을 해보겠습니다.


쉘코드가 잘 출력되는것을 확인 할 수 있습니다 .


놉의 중간 주소를 생각해서 공격을햇으나 세그맨테이션 에러가 뜨는군요


코어덤프를 생성하기 위해서 ulimit -c unlimited를 해준 이후에
tmp에는 이미 고블린의 core파일이 있기때문에 폴더를 하나 더 만든후에 
그 곳에 troll파일을 복사하고 다시 생성하였습니다
[심볼릭링크 파일이여서 코어덤프가 생성이 안되는줄 알았더니 이미 코어파일이 존재하는 상태이고 그 코어파일은 고블린의 권한을 가지고 있기 때문에 생성이 안되던거였습니다. 그래서 새로운 폴더를 생성하여 코어파일이 생성되도록 하였습니다]


그 후에 다시 심볼릭링크 파일을 만든 후에 아까 공격했던 코드를 그대로 다시 써넣은후 세그먼테이션에러가 떠서 생성된 코어덤프를 확인함으로써 
어디가 문제였나 분석해보겠습니다


0xbfffff60 in ?? 라는 문구가 발생하는군요 0xbfffff60으로 찾아 들어가봅시다


확인해보니 \AA를 실행하다가 멈춰버렸습니다. 
왜 \AA인지 확인을 해보겠습니다


./AA인걸 확인할 수 있습니다


좀 더 자세히보면 이렇게 주소가 이뤄져있는걸 보실 수 있습니다.    


놉의 위치를 찾았습니다

[스택 끝 주소는 메모리의 끝주소기 때문에 사용하면 안됩니다.]


쉘의 주소가 확인이 됩니다 스택 끝 주소는 피하고 그 뒤 값인 80쯤을 넣어주면 놉코드를 타고들어가서 성공할거같습니다 .


성공적으로 트롤의 권한을 휙득했습니다 이틀이나 걸린 무시무시한 녀석이였습니다.

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

LOB skeleton  (0) 2016.05.05
LOB vampire  (0) 2016.05.04
LOB orge  (0) 2016.05.02
LOB darkelf  (0) 2016.05.02
LOB wolfman  (0) 2016.05.02



orge의 소스를 열어봤습니다 저번 소스와 크게 변한거는 마찬가지로 없지만
here is changed!
if(strlen(argv[0]) != 77 ) {
printf("argv[0] erro\n");
exit(0);
}
이 부분이 추가됬군요 gdb로 분석해서 해당부분을 읽어보겠습니다 .


35에서 ebp+12 즉 argv[0]의 값을 eax안에 복사합니다 
38번에서 edx에 eax값을 복사하고 
40번에서 edx를 집어 넣습니다 .
41에서는 strlen함수를 호출합니다 .
46에서는 esp에 4 만큼 넓혀서 argv[1]값으로 이동하네요 
49에서는 eax에 eax값을 복사합니다 
51에서는 eax와 77을 비교합니다 .
54에서 eax가 77과 같으면 main+80으로 이동을 합니다 
그렇지않다면 56이후로 쭉 실행을해서 종료를 시킵니다 .

저번처럼 argv[1]에 쉘코드를 넣어서 클리어하는 방식을 똑같이 사용해도 괜찮을거 같습니다. 
근데 제가 여태까지 이용해오던 방식은 argv[1],[2] 이 두개를 이용하였는데 갑작스럽게 argv[0]이 등장하였네요 
배열을 뒤로 움직이는 방법이라도 존재하는것일까요 

일단 주소부터 구해보도록 하겠습니다 


main+224에 브레이크포인트를 잡아준 후에 argv[1] 과 argv[2]의 주소를 구하기 위하여 실행을 햇으나 argv[0]에서 에러가발생하네요
그렇다면 아까 main + 35~ main+ 76 즉 argv[0]을 검사하는 부분에서 브레이크 포인트를 잡은후에 어떡하면 에러가 나지않을까? 하고 한번 찾아보겠습니다 .



argv[0]에 대해서 알기 위해서 이런식으로 무작위로 대입해봤습니다 .
argv[1].[2] 같은 값이 아니라 argv[0]뒤에 잇는 값이라서 무작위로 뒤로 넣으면 되지 않을까? 싶어서 시도해봤습니다.

하지만 모두들 실패했습니다.
그러다가 문득 


Starting program: \tmp\orge `python~~
앞에잇는 \tmp\oreg 뭔가 수상했습니다 스타팅 프로그램에 저렇게 나와있네? 하고 생각이 들더군요 

그래서 이런식으로 시도를 다시 한번 많이 해봤습니다.
main+66 즉 에러 메시지가 뜨는부분에서 열심히 실행을 해봤습니다. 
처음에는 단순히 파일명이 argv[0]일까 생각을 했습니다만 파일명을 정확히 77로 맞춰서 여러번 시도해봐도 모두 실패했습니다 .
Starting program: \tmp\orge `python~~
\tmp\ << 이 친구들이 존재하고잇었습니다 그래서 argv[0]을 비교하는 값인 77에서 -5(\tmp\)를 빼줘서 72자리의 값 만큼 해줬더니


시도 했더니 argv[0] error 라는 메시지가 안뜨네요!




브레이크 포인트를 308에 잡고 실행을 햇더니 argv[0] error 와 세그멘테이션 폴트가 뜨지않네요 !  
그렇다면 아까와 마찬가지로 주소를 구해봐야겠습니다 .


argv[1]의 값이 나옵니다 


argv[2]의 값이 나옵니다 .
저번과 같이 A(44)+쉘코드가잇는 주소의값 (마지막자리는 \xbf) +b(적절한값+쉘코드)가 되겠습니다 .
다만 문제는 권한이 걸려있는 본래에 orge는 제가 임의로 이름을 변경하지 못합니다 .
그러면 어떻게 argv[0] 즉 본래의 orge의 길이를 77이라고 생각하게 만들 수 있을까요 ? 또 여러가지 시도를 해봐야겠습니다 .


[안보이는건 눌러서 봐주세요] 
argv[0]에러가 역시나 발생하네요 그럼 처음에 써봣던 ////를 혹시나해서 사용해보겠습니다 .


세그먼트 에러가 떠서 쉘코드가 들어잇는 주소를 살짝 바꿧습니다 .
권한이 따이네요 신납니다!!


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

LOB vampire  (0) 2016.05.04
LOB troll  (0) 2016.05.04
LOB darkelf  (0) 2016.05.02
LOB wolfman  (0) 2016.05.02
LOB goblin  (0) 2016.05.01


darkelf의 소스입니다
저번 문제에 비해서 추가된것은 
if(strlen(argv[1]) > 48 ) {
printf ("argument is too long!.\n");
exit(0);
}
이거 밖에 없군요 . 음....argv[1]에 조건이 걸려있는걸 보아하니 
argv[2]를 통해 공격하던식으로 또 공격하면 풀릴거같습니다 
제가 시스템에 관하여 초보이기 때문에 너무 날로먹는 치사한 방법을 사용하는것인가 싶기도 하네요...-_-;;


새로 추가된 친구들입니다 .
ebp+12  = argv[0]에 4만큼 공간을 먹게만들어서 argv[1]로 만드네요
그 후에 edx에 넣고 strlen함수를 호출합니다.
+195에서 eax와 48을 비교합니다 지금 eax에는 argv[1]이 담겨잇겠지요
198에서 작거나 같으면 main+224에 보내는군요 그렇지않으면 프로그램이 종료 되버립니다.

뭔가 너무 날먹는거같지만 아까와 똑같이 진행을 해보겠습니다.


"A"*47과 \xbf의 값이 보입니다


"B"의 값들이 보입니다 .
저번과 마찬가지로 공격코드를 짜보겠습니다.

공격에 성공했습니다. 근데 개인적으로 너무 날로먹는거같아서 추가로 gdb분석을 해볼까합니다 .


새로 생긴 main +174쯤에 브레이크포인트를 걸어주겠습니다


에러가 나네요 브포를 잘못 잡앗나봅니다..

그렇다면 main +176으로 잡아보겠습니다


되네요 하하 한번에 잡을수 있도록 더 연습을 해야겠습니다.


eip로부터 두개의 어셈코드를 뽑아냈습니다. 두번 다음 어셈으로 넘어가도 eax값은 변함없이 0xbffffae8이군요 


0xbffffbec를 가리키고있습니다.

쫄래쫄래 따라가보니 아까 argv[1]에 입력한 값이 나오네요 

제가 지금 알고싶은것은 

if(strlen(argv[1]) > 48 ) {
printf ("argument is too long!.\n");
exit(0);}
여기서 48을 초과하면 어떻게 되느냐 정확히는 저렇게 argv[1][2]의 값을 넣어줫는데 strlen부분에서는 정확히 어떠한식으로 반응할까? 이것을 gdb로 보고싶습니다

바로 프린트까지 이동을 해보겠습니다


48만큼 정상적으로 받아들이네요


이번엔 값을 초과하면 어떻게 보나 알기 위해서 48을 초과한 58을 넣어보겠습니다

58만큼 값이 그대로 나오네요 


0x80485cd 즉 printf문에서 한번 더 출력하니 argument is too long이라는 문구가 출력되는걸 볼 수 있습니다! 
뭔가 gdb랑 더 가까워진 기분이네요 음음 
오늘 연습한 분석방법을 이용해서 다음에 더 유용하게 문제풀이를 할 수 잇었으면 좋겠습니다!

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

LOB troll  (0) 2016.05.04
LOB orge  (0) 2016.05.02
LOB wolfman  (0) 2016.05.02
LOB goblin  (0) 2016.05.01
LOB cobolt  (0) 2016.04.30


orc소스와 비슷하지만 뭔가 업그레이드가 됬네요 여기서 먼저
memset함수를 말씀드리자면
memset(a,b,c) = a = 채울 메모리의 주소 b =채울 문자 c = 채우려고 하는 문자의 개수입니다 

음 버퍼로 공격하는걸 막네요 저번 소스와 비슷하고 전 argv[2]를 이용햇었는데 될지 안될지 저 memset이 정확히 무엇을 막는지 햇갈리기 때문에 방금했던 공격을 다시 한번 이용해보겠습니다 .


아까와 같아서 새로 추가된 memset에 대해서만 가져왔습니다.
이 코드를 보니 뭔가 더 이해가 되는군요  
main 214에서 40을넣어주고
main 216에서 0 을넣어주고
main 218에서 버퍼의 주소를 넣어주는군요 
오오... 뭔가 이렇게 하나만 쫙 보니까 좀 더 분석을 다음에 쉽게 할수 잇을거같은 자신감이 생깁니다 .


시그널 SIGSEGV가 실행되면서 와장창 해버리네요


0xbf424242에서 문제가 있다고 하는거같습니다 .
그렇다면 이번에는 A*47 + \xbf를 해보겠습니다


또 에러가 생기네요 혹시 argv[2]가 문제일까요 ? 뺴놓고 실행해보겠습니다

...자세히보네 /tmp/./wolfman을 실행하는군요 -_- 죄송합니다 제대로 다시 gdb를 열어서 처음에 입력햇던것을 다시 한번 실행시켜보겠습니다


성공적이군요! break point는 main+222를 잡아뒀습니다. 


A*47 B*3 \xbf 가 보이는군요 ret값도 포함되어잇겠습니다 .


argv[2]의 A*100 도 마찬가지로 나오네요 

[*팁을 주셔서 글을 추가로 더 적겠습니다 신기하네요!]

gdb에는 nexti라는 기능이 있습니다 
nexti : 다음 기계 명령어까지 응용프로그램을 수행합니다. 라는데요 
지금 브레이크포인트를 main+222지점 즉 memset부분에서 멈춰뒀는데 
nexti 를 사용하게 되면 memset이 실행된 부분을 볼 수 잇겠네요!


띠용...40버퍼만큼 사라져버렸군요 하지만 저는 argv[2]를 통해서 공격을합니다
고로 제가 푸는 방법과는 무관하다는것을 알게되었습니다.
그럼 공격을 해보겠습니다


성공했습니다! 잠시 쉬었다가 계속 문제를 풀어야겠습니다 오늘은 3~4시정도에 자야겠군요 다음날 학교를 가야해서.. ㅠㅠ

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

LOB orge  (0) 2016.05.02
LOB darkelf  (0) 2016.05.02
LOB goblin  (0) 2016.05.01
LOB cobolt  (0) 2016.04.30
LOB gremlin  (0) 2016.04.30


버퍼가 40이 할당되어있습니다!
argc<2 일시 에러를 띄우고 종료를 해버리네요 
egghunter에 보면 memset이라는 함수가 있네요

memset 참고 : http://itguru.tistory.com/104

egghunter는 미리 말씀 드리자면 환경변수와 에그쉘을 무효화 시킵니다

argv[1] 즉 첫번째 인자의 48번째 글자?는 /xbf여야합니다 안그러면 문구를 띄우고 종료를 시켜버리네요 

또한 argv[1]을 strcpy를 이용해서 버퍼에 복사한후에 출력해버리네요 
[strcpy 취약점 - 복사할때 크기를 체크하지않는다]

저는 여태까지 환경변수와 에그쉘을 이용하지 않앗기에 평소처럼 풀면되는 문제같네요 일단 gdb로 봐보겠습니다


<main> push %ebp
<main+1> mov %ebp , %esp
스택프레임을 설정하였습니다
<main+3> sub %esp , 44
buf 와 i 의 크기 총 44를 확장해줬습니다
<main+6> cmp DWORD PTR [%ebp+8] , 1
argc 과 1을 비교한다
<main+10> jg 0x8048523 <main+35>
argc가 1보다 클 경우 main+35로 이동한다
<main+12> push 0x8048630
stdin같은 입력스트림을 넣어줍니다
<main+17> call 0x8048410 <printf>
printf 함수를 호출합니다
<main+22> add %esp,4
printf에서 사용한 인자를 정리해줍니다
<main+25> push 0 
0을 넣어줍니다
<main+27> call 0x8048420 <exit>
exit 함수를 호출합니다
<main+32> add  %esp , 4
exit인자를 정리해줍니다
<main+35> nop
필요없음
<main+36> mov DWORD PTR [%ebp-44] , 0x0 
0을 %ebp-44의 주소에 넣는다 
<main+43> nop
필요없음
<main+44> lea %esi , [%esi*1]
%esi에 [%esi*1]의 주소값을 넣어줍니다
<main+48> mov %eax,DWORD PTR [%ebp-44]
eax에 [%ebp-44]의 주소값을 넣어줍니다
<main+51> lea %edx , [%eax*4]
edx에 [%eax*4]의 주소값을 넣어줍니다
<main+58> mov %eax,%ds:0x8049750

<main+63> cmp DWORD PTR [%eax+%edx] ,0
[%ebp-44 + %eax*4] 의 값과 0을 비교합니다
<main+67> jne 0x8048547 <main+71> 
위에서 비교한 값이 같지 않으면 <main+71>로 이동합니다
<main+69> jmp 0x8048587 <main+135>
같으면 <main+135>로 점프합니다



간단히 스택을 표현하자면
buf   sfp   ret   argc   argv

         40     4      4    4      4      
ebp - 40  ebp  ebp+4  ebp+8   ebp++@    
이렇게 되잇는걸 알 수 있습니다 .

main ~ main+3 : 44바이트만큼 주어졌네요 buf[40]의 크기와 i[4]의 크기라고 짐작가능합니다 .
main+6 ~ main+35 : if문 부분이네요 ebp+8[argc]이 2이상이면 main+35로 점프하고 2미만일경우 프로그램을 종료시켜버리네요 

<main+71> mov %eax , DWORD PTR [%ebp-44]
eax에 [%ebp-44]의 주소값을 넣어줍니다
<main+74> lea %edx , [%eax*4]
edx 에 [%eax*4] 주소를 넣어줍니다 
<main+81> mov %eax,%ds:0x8049750
eax에 0x8049750을 넣어준다
<main+86> mov %edx , DWORD PTR[%eax+%edx]
edx에 [%ebp-44] + [%eax*4] 의 주소를 넣어준다
<main+89> push %edx  
edx를 스택에 넣어준다 
<main+90> call 0x80483f0<strlen>
strlen 함수를 호출한다
<main+95> add %esp , 4
4의 공간을 사용한다
<main+98> mov %eax , %eax 
eax에 eax를 집어넣는다
<main+100> push %eax 
eax를 스택에 집어넣는다 
<main+101> push 0
0을 집어넣는다
<main+103> mov %eax, DWORD PTR[%ebp-44]
eax에 [%ebp-44]의 주소를 넣는다 
<main+106> lea %edx,[%eax*4]
edx에 [%eax*4]를 넣는다
<main+113> mov %eax,%ds:0x8049750
eax에 0x8049750을 넣는다
<main+118> mov %edx , DWORD PTR [%eax+%edx]
edx에 %eax+%edx의 주소를 넣어준다
<main+121> push %edx
edx를 스택에 넣어준다
<main+122> call 0x8048430 <memset>
memset 함수를 호출한다
<main+127> add %esp , 12
12만큼 사용합니다
<main+130> inc DWORD PTR [%ebp-44]
[%ebp-44]의 주소값이 1 증가합니다
<main+133> jmp 0x8048530 <main+48>
main+48로 이동합니다
<main+135> mov %eax,DWORD PTR [%ebp+12]
eax에 argv[0] 을 넣어줍니다
<main+138> add %eax , 4 
eax에 4를 더해줍니다 
<main+141> mov %edx,DWORD PTR [%eax]
edx에 argv[1]을 넣어줍니다
<main+143> add %edx,47
argv[1]에서 47을 더해줍니다 
<main+146> cmp BYTE PTR [%edx] , 0xbf
argv[1][47]의 주소를 0xbf와 비교합니다
<main+149> je 0x80485b0 <main+176>
argv[1][47]과 0xbf가 같으면 <main+176>으로 이동합니다
<main+151> push 0x804863c
stdin 함수를 넣어줍니다
<main+156> call 0x8048410 <printf>
printf 함수를 넣어줍니다
<main+161> add %esp , 4 
printf가 사용한 인자를 정리해준다
<main+164> push 0 
0을 넣어준다
<main+166> call 0x8048420 <exit>
exit 함수를 호출합니다
<main+171> add %esp , 4
exit가 사용한 인자를 정리해준다
<main+174> mov %esi , %esi
esi에 esi를 넣어줍니다 
<main+176> mov %eax,DWORD PTR [%ebp+12]
eax에 argv[0]의 주소를 넣어줍니다 
<main+179> add %eax , 4
eax에 4를 넣어줍니다
<main+182> mov %edx , DWORD PTR [%eax]
edx에 argv[1]의 주소를 넣어줍니다
<main+184> push %edx
edx를 스택에 넣어줍니다
<main+185> lea %eax , [%ebp-40]
eax에 [%ebp-40]의 주소값을 넣어줍니다 
<main+188> push %eax 
ebp-40의 주소를 넣습니다
<main+189> call 0x8048440 <strcpy>
strcpy 함수를 호출합니다 
<main+194> add %esp , 8 
strcpy 함수가 사용한 인자를 정리해줍니다 
<main+197> lea %eax , [%ebp-40]
eax에 [%ebp-40]의 주소값을 넣어줍니다 .
<main+200> push %eax
ebp-40을 스택에 넣어줍니다 
<main+201> push 0x8048659
stdin을 넣어줍니다
<main+206> call 0x8048410 <printf>
printf 함수를 호출합니다 
<main+211> add %esp , 8 
printf 함수가 사용한 인자를 정리해줍니다 
------------------------추가했습니다-------------------------------------------------------


main+36부터 for문이 시작됩니다
main+44는 데이터를 복사하는거같습니다(확실치 않습니다 )
48~63까지는 i = 0으로 초기화 하는 작업같습니다 
67에서는 값이 같지 않으면 71로 점프를 합니다 
69에서는 main+135로 이동합니다 

71에서는 eax값에 ebp-44를 복사하였습니다 

74에서는 eax*4만큼을 edx에 복사합니다 (주소값..?)
81에서는 eax에 ds:0x8049750의 값을 넣습니다(데이타 세그먼트가 아닐까요?)
86에서는 eax와edx를 합해서 edx에 넣습니다.
89에서는 edx를 넣습니다 .
90에서는 strlen을 호출하네요 
95에서는 스택을 4바이트만큼 줄입니다 
98에서는 eax값에 eax를 넣습니다 (어떤 의미일까요 ?)
100에서는 eax를 넣습니다
101에서는 0을 넣습니다
103에서는 eax값에 ebp-44를 복사합니다
106에서는 eax*4에 저장되있는 값을 edx에 넣습니다 .
113에서는 ds:0x8049750의 값을 eax에 복사합니다 
118에서는 eax와 edx를 합한값을 edx에 복사합니다 
121에서는 edx를 넣습니다
122에서는 memset을 호출합니다
127에서는 스택을 12만큼 줄입니다 
130에서는 ebp-44를 1만큼 증가시킵니다 
133에서는 main+48로 이동합니다
135에서는 ebp+12를 eax에 복사합니다 
138에서는 eax에서 4만큼 줄입니다
141에서는 eax를 edx에 복사합니다
143에서는 edx에서 47만큼 줄입니다 
146에서는 edx와 0xbf가 값이 같다면
149에서는 main+176으로 이동합니다
151에서는 0x804863c만큼 넣어줍니다
156에서는 printf를 호출합니다
161에서는 esp에서 4만큼 줄입니다
164에서는 0만큼 넣어줍니다
166에서는 exit를 호출합니다
171에서는 esp에서 4만큼 줄입니다
174에서는 esi값을 esi에 복사합니다
176에서는 eax에 ebp+12만큼의 값을 넣습니다
179에서는 eax에서 4만큼을 줄입니다
182에서는 eax의값을 edx에 복사합니다
184에서는 edx의값을 넣습니다
185에서는 eax에 ebp-40에 저장되잇는 값을 넣습니다 
188에서는 eax를 넣습니다
189에서는 strcpy를 호출합니다
194에서는 esp에서 8만큼 줄입니다
197에서는 ebp-40에잇는값을 eax에 넣습니다
200에서는 eax를 넣습니다
201에서는 0x8048659를 넣습니다
206에서는 printf를 호출합니다
211에서는 esp에서 8만큼 줄입니다 

제가 제대로 분석한것인지는 모르겠습니다..
69에서 130과 133을 보시면 environn[i]의 조건문 부분이고 i++의 증감에 대해서 표현되잇다는걸 아실겁니다 

90과 100을 보시면 strlen함수를 실행합니다
101에서는 두번째로 0을 넣습니다
121까지는 0x8049750 [eax+edx]를 이용하여서 environ을 넣는다는건 알겟습니다만 제대로 이해가 가지 않습니다 (gdb로 여러가지를 해봤는데 짧은 지식으로는 실패하였습니다 ㅠㅠ 아시는분은 도와주세요 배우고 싶습니다)

135에서는 ebp+12의 값 즉 argv[0]을 eax에 저장하네요
138에서는 4만큼의 값을 할당한 즉 argv[1]의 값을 만든다고 생각할 수 있습니다 
*햇갈려서 맞지 않을 수 있으니 참고만 해주세요 *
141에서는 argv[0] , [1]의 값을 edx에 넣고
143에서는 edx에 47만큼의 값을 할당하는것을 보아하니argv[1][47]을 예상할수잇군요 
146에서는 0xbf와 값을 비교한 후에
149에서 같을경우 176으로 이동을해서 프로그램을 쭉 진행하지만 틀릴경우 종료시킵니다.

176에서는 ebp+12 즉 argv[0]을 데려오고 
179에서 4만큼 할당해서 argv[1]의 주소를 가리키고있네요 
182에서 argv[1]의 주소를 edx에 저장합니다 
184에서 edx를 넣습니다 (여기서 strcpy(buffer, argv[1]) 부분이 이뤄지는게 아닐까 예상해봅니다 지식이 부족해서 확신을 못하겠습니다.)
185에서 buffer[40]의 주소를 eax에 넣네요 
189에서 strcpy를 호출합니다
194에서 esp에 8만큼을 줄이고
197에 eax 에 ebp-40의 주소를 넣네요
이렇게 대충 분석이 끝난거 같습니다..정말 허접하군요 lob를 끝마치는 날에는 완벽해져있기를 바랍니다 -_-;

공격코드를 테스트 해보려고 gdb로 디버깅을 하던차에 
Program exited with code 01. 이라는 에러가 뜨네요
Program exited with code 01. 은 다른 유저의 setUid가 걸려있어서 디버깅이 안되는 에러입니다  
이상하네요 tmp에 복사해서 한거같은데...


tmp폴더 내에서 ./를 붙여서 실행하지 않으면 본래 루트에 있던 원본이 실행되는거 같군요 신기합니다 처음알았어요 


0xbffffad4 의 세번 째 칸을 보시면 0xbf424242가 출력된것을 보실 수 있습니다.
저 곳이 아마 리턴주소겠구요


이 주소가 argv[2]의 주소라고 생각할 수 있습니다.
그렇다면 a[44]+ret주소값(마지막 자리는 \xbf)+argv[2](쓰레기값들 + 쉘코드)
이렇게 구성될 수 있을거같네요 

와 진짜 욕나오네요 ㅎㅎ bash2를 설정안해서 두시간동안 코어덤프 보면서 꼐에속 해맷습니다 계에솟고소오오오오옥 와 열받내요~~깔깔깔깔깔깔깔

사람 매우 열받게 하는 lob였습니다 .

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

LOB darkelf  (0) 2016.05.02
LOB wolfman  (0) 2016.05.02
LOB cobolt  (0) 2016.04.30
LOB gremlin  (0) 2016.04.30
LOB gate  (0) 2016.04.30

안녕하세요 개인적으로 많이 삽질한 문제였습니다 .. 

goblin의 소스코드입니다 

gets 함수를 쓰고있네요 gets 함수는 엔터를 누를때까지 문자열로 입력을 쭈우욱 받아들여서 
버퍼오버플로우를 만드는 취약점을 가진 함수랍니다 (그래서 fgets를 사용하는것을 권장하죠?)

처음에 생각햇던 페이로드 구성도입니다

A*20(buf+sfp)+4(버퍼 오버 플로우시켜서 리턴주소를 쉘코드의 주소가 담긴부분으로 변경할곳)+B*100(쉘코드를 담기위한부분)+25(쉘코드) 이렇게 생각을 해두었습니다.

<main> push %ebp
<main+1> mov %ebp,%esp
스택 프레임을 설정하였다
<main+3> sub %esp,16
esp에서 16을 뺴줬습니다 [buf를 16만큼 할당]
<main+6> lea %eax , [%ebp-16]
eax에 ebp-16의 주소를 넣어줬습니다 
<main+9> push %eax
스택에 ebp-16의 주소를 넣어줬습니다
<main+10> call 0x804830c <gets>
gets 함수를 호출합니다
<main+15> add %esp,4
gets의 인자값 정리
<main+18> lea %eax, [%ebp-16]
eax에 [%ebp-16]의 주소를 넣어줍니다
<main+21> push %eax
eax를 스택에 넣습니다
<main+22> push 0x8048470
stdin같은 함수겟지요? 넣어줍니다
<main+27> call 0x804833c <printf>
printf 함수를 호출합니다
<main+32> add %esp , 8 
printf의 인자값 정리

gdb로 대강 분석을 해보겠습니다 .
main+3 버퍼의 크기만큼 할당되었군요 
그 후에 main+6 부터 gets함수로 입력을 받은뒤 ebp-16에다가 넣어버리네요 

이번 문제는 삽질을 엄청 많이했습니다...

먼저 브레이크 포인트를 main+15지점에 걸어두었습니다 gets함수가 쓰인 직후죠

그 뒤에 gdb에      "A"*20 +"B"*4 +"C"*100 

`python -c 'print "A"*20 +"B"*4+"C"*100`'  

등등등등...많이 넣어봤습니다 

이렇게 나온 주소값들을 일일히 넣어보고 x/~~x $esp x/~~x$ebp-16 등등  여러가지 명령어를 또 사용해봐서 나온 주소값들을 넣어봐도 
반응이없거나 쉘이들어가기만 하고 제대로 안된다거나 하는 경우들이 계속 발생하였습니다 ..

일단 스택을 대충 생각해보겠습니다 

  buf      sfp     ret    쉘코드를 넣기위한친구들 + 쉘코드 
ebp-16   ebp  ebp+4                 ebp+8 

대충 이러하게 스택의 위치가 잡혀있을거같다는 생각으로 시도를 해봤는데도 열리지않았습니다 ..

또한 공격을 할때 gets 함수는 파이프 함수를 써야 하는것을 잊고 

`python -c 'print "A"*100 +"주소값"+"B"*100+"쉘코드"`' 이러한 식으로 공격을 해서 계속 해맷습니다 -_-;; 

여하튼..gets 함수는 문자열로 쭈욱 인식하는 함수기에 파이프를 이용했습니다 

파이프란 왼쪽 명령어 친구들을 오른쪽으로 보내주는 역할을합니다.


정말 간단하게도 이렇게 값을 넣었습니다 

쉽게 주소 파악을 위해서 A(buf+sfp=20) B(RET) C(그냥막넣음) 이렇게 했습니다 


414141 4242424 434343 . . . .값이 나오는걸 볼 수 있습니다 .
여기서 C를 이용해 쉘코드를 넣어야 하기 때문에 쉘의 일정한 주소값을 (전 적절하게 중간즈음을 택했습니다 .)


(눌러서 봐주세요)

이러한식으로 처음 생각했던 공격코드를 짯더니 드디어 열렸습니다 .
처음에 짠 공격코드를 파이프를 통해서 ./goblin으로 보내버린겁니다 

간단하기도 하지만 하나의 간단하고도 사소한 실수때문에 많은 시간이 소요되버렸네요 -_- 좀 더 공부를 열심히 해야겠습니다 

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

LOB darkelf  (0) 2016.05.02
LOB wolfman  (0) 2016.05.02
LOB goblin  (0) 2016.05.01
LOB gremlin  (0) 2016.04.30
LOB gate  (0) 2016.04.30

+ Recent posts