💡 strncpy()로 selection_func 호출 시 받은 인자 src를 30byte char 배열 dest로 복사
💡 이때, dest 배열은 30byte인데 strncpy로 준 size_t 인자 값은 0x1Fu (10진수 31)이다.
--> overflow...?!
그 후,
strcmp 함수에서 복사된 dest에 있는 문자열과 "one" 문자열 비교 후 동일한 경우 if문 안으로 진입하여
v3가 담고있는 함수의 주소를 one으로 바꾼다.
one() , two()
각각 "This is function one/two!"라는 문자열을 출력한다.
return v3();
v3에 들어있는 함수의 주소에 따라 return에서 실행하는 함수가 바뀐다는 의미로 위의 두 함수를 만든 듯 하다.
ida에서 함수 list를 보니,
print_flag()라는 누가봐도 flag와 연관있는 듯한 함수가 있다.
print_flag()
print_flag가 호출되면 flag.txt 파일에서 flag를 한 글자씩 읽어 출력해준다.
⭐ Solve Tips
즉, 위의 select_func 함수의 return문에서 실행할 v3()에 들어갈 함수 주소를 조작하여 print_flag가 호출되도록 하면 flag를 얻을 수 있게 된다.
5. gdb-peda로 디스어셈블
offset 파일은 PIE 보호기법이 적용된 파일이라
고정된 실제 주소값이 아닌 offset 값 (기준점으로부터 계산된 거리 값)이 확인된다.
gdb-peda에서 info func (i fu) 명령을 수행하니 함수들의 offset 주소가 나온다.
위에서 보았던 strncpy 함수에서의 copy size로 인한 overflow 가능성 언급했던 부분을 상기해보면,
요점은 다음과 같다.
point 1.
우리가 입력하는 값을 gets(s)로 받고 select_func에 src 인자로 받아 strncpy()를 수행하는 것
point 2.
strncpy()의 경우 3번째 인자로 복사할 데이터의 size를 지정하는데 이 때 복사받을 dest 배열은 30byte,
그러나 지정된 copy size가 0x1Fu (=31byte)
point 3.
PIE 보호기법으로 함수들은 고정 주소가 아닌 offset으로 표현되는데
위의 gdb 수행 내용을 보면, two 함수와 print_flag 함수의 offset 차이가 1byte밖에 안 나는 것을 확인
select_func에서 보다시피 dest 배열과 v3 함수 포인터 변수는 스택에서 인접해 있고 offset 차이는 30byte. 그런데 strncpy를 통해 1byte overwriting이 가능해지므로 v3가 가리키는 two() offset 값을 그대로 두고print_flag에서 two의 offset 값과 달랐던 그 1byte를 덮어씌우면된다.
6. Exploit Code 작성
지금까지 파악한 내용을 토대로 exploit 코드를 작성해보자
단순하게 dest를 0x41('A')로 채우고 나머지 1byte를 0xd8로 해서 payload를 보낸다.
[Pwnable] offset
1. offset file download
실행 시켜보면 permession denied가 뜬다.
2. nc 접속
호출하고 싶은 입력하래서 printf 입력했더니 그냥 종료된다.
일단 gdb로 분석해보자
3. 보호기법 확인
checksec으로 걸려있는 보호기법부터 확인
4. IDA로 execute flow 분석
pseudo 코드
main()
호출할 함수 이름을 gets()로 받아와서 select_func()에 인자로 주며 호출한다.
select_func()
int (*v3)(void); ->int형 함수 포인터
함수 포인터 참고 글
v3 = two; -> two 함수를 가리키는 함수 포인터 변수 v3
💡 strncpy()로 selection_func 호출 시 받은 인자 src를 30byte char 배열 dest로 복사
💡 이때, dest 배열은 30byte인데 strncpy로 준 size_t 인자 값은 0x1Fu (10진수 31)이다.
--> overflow...?!
그 후,
strcmp 함수에서 복사된 dest에 있는 문자열과 "one" 문자열 비교 후 동일한 경우 if문 안으로 진입하여
v3가 담고있는 함수의 주소를 one으로 바꾼다.
one() , two()
각각 "This is function one/two!"라는 문자열을 출력한다.
return v3();
v3에 들어있는 함수의 주소에 따라 return에서 실행하는 함수가 바뀐다는 의미로 위의 두 함수를 만든 듯 하다.
ida에서 함수 list를 보니,
print_flag()라는 누가봐도 flag와 연관있는 듯한 함수가 있다.
print_flag()
print_flag가 호출되면 flag.txt 파일에서 flag를 한 글자씩 읽어 출력해준다.
⭐ Solve Tips
즉, 위의 select_func 함수의 return문에서 실행할 v3()에 들어갈 함수 주소를 조작하여 print_flag가 호출되도록 하면 flag를 얻을 수 있게 된다.
5. gdb-peda로 디스어셈블
offset 파일은 PIE 보호기법이 적용된 파일이라
고정된 실제 주소값이 아닌 offset 값 (기준점으로부터 계산된 거리 값)이 확인된다.
gdb-peda에서 info func (i fu) 명령을 수행하니 함수들의 offset 주소가 나온다.
위에서 보았던 strncpy 함수에서의 copy size로 인한 overflow 가능성 언급했던 부분을 상기해보면,
요점은 다음과 같다.
point 1.
우리가 입력하는 값을 gets(s)로 받고 select_func에 src 인자로 받아 strncpy()를 수행하는 것
point 2.
strncpy()의 경우 3번째 인자로 복사할 데이터의 size를 지정하는데 이 때 복사받을 dest 배열은 30byte,
그러나 지정된 copy size가 0x1Fu (=31byte)
point 3.
PIE 보호기법으로 함수들은 고정 주소가 아닌 offset으로 표현되는데
위의 gdb 수행 내용을 보면, two 함수와 print_flag 함수의 offset 차이가 1byte밖에 안 나는 것을 확인
6. Exploit Code 작성
지금까지 파악한 내용을 토대로 exploit 코드를 작성해보자
단순하게 dest를 0x41('A')로 채우고 나머지 1byte를 0xd8로 해서 payload를 보낸다.
flag를 얻었다.
150 points 획득
'Wargame > HackCTF' 카테고리의 다른 글