[pwnable.xyz] two targets(50 pts) :: Write-Up
두비니
·2020. 10. 10. 19:18
Which one would you exploit?
문제 자체는 되게 직관적이네요. 1~3번으로 준비를 한 뒤에 4번으로 shell을 따면 되려나봐요 그쵸?
아이다로 더 자세히 봅시다.
문제분석
// local variable allocation has failed, the output may be wrong!
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
char *v3; // rsi
const char *v4; // rdi
signed int v5; // eax
char s; // [rsp+10h] [rbp-40h]
__int64 v7; // [rsp+30h] [rbp-20h]
char *v8; // [rsp+40h] [rbp-10h]
unsigned __int64 v9; // [rsp+48h] [rbp-8h]
v9 = __readfsqword(0x28u);
setup(*(_QWORD *)&argc, argv, envp);
v3 = 0LL;
v4 = &s;
memset(&s, 0, 0x38uLL);
while ( 1 )
{
while ( 1 )
{
print_menu();
v5 = read_int32(v4, v3);
if ( v5 != 2 )
break;
printf("nationality: ");
v3 = (char *)&v7;
v4 = "%24s";
__isoc99_scanf("%24s", &v7);
}
if ( v5 > 2 )
{
if ( v5 == 3 )
{
printf("age: ");
v3 = v8;
v4 = "%d";
__isoc99_scanf("%d", v8);
}
else if ( v5 == 4 )
{
v4 = &s;
if ( (unsigned __int8)auth((__int64)&s) )
win(&s);
}
else
{
LABEL_14:
v4 = "Invalid";
puts("Invalid");
}
}
else
{
if ( v5 != 1 )
goto LABEL_14;
printf("name: ");
v3 = &s;
v4 = "%32s";
__isoc99_scanf("%32s", &s);
}
}
}
일단 필요한 부분만 분석을 해봅시다. getshell이 4번 선택지였으니 거기부터 봅시다.
else if ( v5 == 4 )
{
v4 = &s;
if ( (unsigned __int8)auth((__int64)&s) )
win(&s);
}
auth함수의 인자로 s를 넣어서 리턴값이 1이면 win함수를 실행시켜주네요. 이게 아마 첫 번째 타겟이겠죠?
win함수는
당연히 플래그를 출력시켜주는 함수고,
이건 auth함수입니다. 결국 여기서 중요한건 다음 부분인데
for ( i = 0; (unsigned int)i <= 0x1F; ++i )
s1[i] = ((*(_BYTE *)(a1 + i) >> 4) | 16 * *(_BYTE *)(a1 + i)) ^ *((_BYTE *)main + i);
다음 식을 통해서 s1을 구합니다. 맨 처음에 저 수학적 수식을 보고 해석해보려고했는데, 해석이 안될 뿐더러 문제 제목이 two target인걸 보고 그냥 손절했습니다ㅎㅎ 안녕!
+) 나중에 추가로 찾아봤는데 리버싱으로 푼 분도 계시더라구요. 뭐 단순히(는 아니겠지만) 역연산을 구하면 되니 적절한 값을 넣어도 할 수는 있겠네요.
보호기법을 확인해보면, 일단 PIE가 없어서 got overwrite도 생각해 볼 수 있고, full relro가 아니라 bss말고도 다른 영역도 이용할 수 있네요.
그래서 일단 다른 부분에서 취약점을 찾아봅시다.
다른곳은 다 괜찮은데 여기 nationality를 입력받는 곳에서 v7에 24바이트만큼 입력을 받는데, v7은 16바이트밖에 되지 않습니다. 즉, v7의 입력을 통해 그 밑의 v8까지 overwrite가 가능합니다.
그럼 v8을 가지고 어떻게 할 수 있는가 봅시다.
아하... 끝나버렸네요
age를 입력하는 부분에서 입력받을 때 v8의 주소인 &v8이 아닌 그냥 v8의 값 자체에 입력을 받고 있습니다. 그러면 시나리오는 다음과 같습니다.
시나리오
1. 국적 입력을 이용하여 v8까지 buffer overflow를 함.
1-2. 이때 v8에 들어갈 내용은 strncmp의 got주소. (PIE기법이 걸려있지 않기 때문에 GOT overwrite 사용 가능)
2. 나이 입력을 이용하여 win함수의 주소를 입력. (단, %d로 받고 있기 때문에 10진수로 입력해야함)
3. 다시 실행시켜서 exploit
페이로드
사실 원래는 printf로 덮어서 하려고 했는데 무슨 이유인지 안되더라구요... 이건 알게되면 더 서술함
나중에 역연산도 만드는걸로ㄲ
'War Games > pwnable.xyz' 카테고리의 다른 글
[pwnable.xyz] note(50 pts) :: Write-Up (0) | 2020.10.09 |
---|---|
[pwnable.xyz] grownup(50 pts) :: Write-Up (0) | 2020.09.17 |
[pwnable.xyz] misalignment(50 pts) :: Write-Up (0) | 2020.09.08 |
[pwnable.xyz] xor(50 pts) :: Write-Up (0) | 2020.08.12 |
[pwnable.xyz] Add(50 pts) :: Write-Up (0) | 2019.11.06 |