Dork's port

FTZ Level19 Write-up(FTZ Level19 풀이) 본문

Hackerschool FTZ Write-up

FTZ Level19 Write-up(FTZ Level19 풀이)

Dork94 2018. 3. 26. 08:50

대망의 19번 입니다!


점점 문제가 갈수록 불친절해지는 것 같은건 기분탓... 인가요?


문제를 보면 이번엔 아무것도 없이 buf만 입력받고 땡이네요!


그래도 attackme파일엔 setuid가 설정이 되어있는데 예전엔 보이던 /bin/sh실행 명령어와 setrueid가 보이지 않아요..


그러면 우리가 만들어 줘야 겠군요!



일단 리턴 어드레스 확인을 위해 아래와 같이 명령어를 작성하였는데 44번째에서 Segemantation Fault가 뜨는 것을 보니 저기가 리턴어드레스 주소인가보군요!


자 그러면 우리는 seteruid및 /bin/sh실행을 위한 쉘코드를 작성하여야 합니다.


이전까지 /bin/sh쉘코드는 많이 이용 하셨을 것이라 생각합니다.


그래서 이번엔 setreuid에 대한 쉘코드를 만들어 볼게요!


기계어를 얻어오기 위해 아래와 같이 코드를 짜고 컴파일을 합니다.


$ gcc -static -g -o setId setId.c


main을 보면 아래와 같이 0xc1c(3100)값을 두번 넘겨주고 setreuid를 호출하네요!


그리고 아래의 명령어로 setreuid를 참조하면 아래와 같은 구문을 확인 할 수 있습니다.


(gdb) disass setreuid



처음에 위의 명령어로 진입하게 되면 꽤 긴 코드가 보이는데 je처럼 조건문을 일일히 가보면 __errno_location으로 jmp하는 명령어를 제외하면 아래의 주소로 이동한 다는 것을 알 수 있습니다.


즉, 에러의 경우가 아닌 정상적인 경우가 아래의 경우 입니다.


0x8과 0xc 를 eax, ecx에 저장하는군요 이때 0x8와 0xc는 main에서 전달 받은 인자 값 입니다.


아래의 코드를 차근차근 따라가보면 아래와 같이 셋팅하여 int 0x80하면 되는 것을 알 수 있습니다.


ecx = setreuid의 첫번째 인자


ebx = setreuid의 두번째 인자


eax = 0x46(setreuid의 값)


int 0x80 = interrupt 함수 호출 


그러면 위의 함수 규칙에 맞게 어셈블리 언어를 코딩해 봅시다. 


이때 NULL값이 들어가지 않도록 xor을 잘 이용하여 설정해 주시기 바랍니다!


아래는 제가 이전에 사용하였던 /bin//sh실행 쉘코드 입니다.


여기 위에 setreuid의 함수 호출양식에 맞게 Asm코드를 작성 합니다.


저 같은 경우엔 아래와 같이 작성하였습니다.


 

void main()
{
        __asm__ __volatile__(
                        "xor %ebx, %ebx         \n\t"
                        "mov $0xc1c, %bx        \n\t"
                        "mov %ebx, %ecx         \n\t"
                        "xor %eax, %eax         \n\t"
                        "mov $0x46, %al         \n\t"
                        "int $0x80              \n\t"
                        "xor %eax, %eax         \n\t"   //Make Null value to avoid 0x00 "
                        "push %eax              \n\t"
                        "push $0x68732f2f       \n\t"
                        "push $0x6e69622f       \n\t"
                        "mov %esp, %ebx         \n\t"
                        "push %eax              \n\t"
                        "push %ebx              \n\t"
                        "mov %esp, %ecx         \n\t"
                        "mov %eax, %edx         \n\t"
                        "mov $0xb, %al          \n\t"
                        "int $0x80              \n\t"
                        );
}


그리고 작성한 소스코드를 컴파일하여 실제로 00(NULL)이 들어가지 않는지 gdb로 확인 합니다.



해당 기계어를 eggshell의 shellcode부분으로 대치해 줍니다.




그리고 eggshell을 실행하여 RET의 주소로 해당 주소를 주면~~~


짜라란 성공했습니다!


쉘코드를 처음부터 직접짜보느라 시행착오도 많고 시간도 오래걸린 편 이었지만


얻는게 많은 라운드 였습니다!


드디어 마지막이네요!!!!


저도 좀 자고 일어나서 풀어봐야 겠습니다!


마지막까지 화이띵!

Comments