인프런 강의 <해킹 대회를 위한 시스템 해킹 프로토스타 완벽 풀이집>의 섹션 0, 1 강의를 듣고 칼리 리눅스 환경 구축과 스택에 관한 기본 리버싱 개념을 공부했다.
stack0
문제해결
//문제 코드
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
modified = 0;
gets(buffer);
if(modified != 0) {
printf("you have changed the 'modified' variable\n");
} else {
printf("Try again?\n");
}
}
modified 값이 0이 아니게 만들어야 해결할 수 있는 것 같다.
//스택 구성
| buffer[64] |
|---------------------|
| modified |
|---------------------|
| ebp |
|---------------------|
| ret |
|---------------------|
일부러 취약하게 컴파일(요즘엔 알아서 고쳐주기 때문에)
바뀌는 모습
./stack0
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
gdb분석
set disassembly-flavor intel : intel 형식으로 바꿔주기
disas main :메인 함수를 디버깅
if문 이라 예상할 수 있는 곳이 test 부분 > breack point를 걸어주기
b *주소 : break point 설정
bp 걸린 모습
eax 값을 확인했을 때 0 으로 변조 안 된 상태 임을 확인 가능
info reg ($~) : 특정 레지스터 혹은 전체 레지스터 정보 확인
여기서 continue 하면 try again 이 뜨겠다..도 예측 가능
run 으로 처음부터 다시 시작해서 버퍼 이상으로 넣어주고
info reg $eax : eax 값을 확인해보면 채워진 게 확인됨
modified로 예상하고 있는 [rbp-0x4] 을 확인해보기 위해
info reg $rbp : rbp 레지스터의 정보 확인
0xfffffffdde0 , [rbp-0x4]는 0xfffffffdde0 - 0x4
스택 구조에서 살펴보면 0x61(=a)로 채워진 모습을 확인할 수 있음 > 변조됨
x/30gx $rsp : 메모리를 16 진수로 표시하고 스택 포인터($rsp)를 기준으로 주변 메모리 내용 출력
x : 메모리 검사, /30 : 출력할 메모리의 단위 수, g : 8바이트(64비트) 값, x : 16진수 형식, $rsp : 현재 스택의 상단 주소를 가리키며, 스택의 가장 최근에 추가된 데이터를 가리킴
stack1
1-1 다른 변수 덮어씌우기
buffer |
modified |
ebp |
rep |
↑ 이런 식으로 쌓임
버퍼를 가득 채우면 밑의 데이터들이 변조가 될 수 있다.
스택 공격에 취약한 컴파일 명령어
gcc –z execstack –no–pie –w -o stack0 stack0.c : stack0.c라는 C언어 소스 코드 파일을 컴파일하여 ‘stack0’이라는 실행 가능한 바이너리 파일을 생성하며, 실행 스택 보호를 끄고, PIE를 사용하지 않으며, 경고 메시지를 비활성화함.
gcc : GNU Compiler Collection의 C컴파일러를 실행하는 명령어. C언어 소스 코드를 컴파일해 실행 가능한 프로그램을 생성함.
-z execstack : 실행 스택 보호(프로그램이 실행 중에 스택 메모리를 수정하는 것을 방지하는 보안 기능)를 끔. 스택을 실행할 수 있는 권한을 줌.
-no–pie : Position Independent Executable(PIE) 형식(실행 파일을 메모리에 로드할 때 위치 독립적으로 로드하는 방식, 보안 향상에 사용)을 사용하지 않도록 함.
-w : 컴파일러의 경고 메시지를 비활성화.
-o stack0 : 출력 파일의 이름을 지정, 즉 stack0이라고 저장.
stack0.c : 컴파일하려는 C언어 소스 코드 이름. 이 파일은 컴파일러에 의해 컴파일되어 실행 파일이 생성됨.
문제해결
//문제 코드
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
if(argc == 1) {
errx(1, "please specify an argument\n");
}
modified = 0;
strcpy(buffer, argv[1]);
if(modified == 0x61626364) {
printf("you have correctly got the variable to the right value\n");
} else {
printf("Try again, you got 0x%08x\n", modified);
}
}
modified 값이 0x61626364(=abcd) 여야 할 것 같다. > stack0 문제와 다르게 특정한 값 요구
버퍼를 넘치게 채워주고 리틀 엔디안 방식에 맞춰dcba로 넣어주면 된다
./stack1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdcba
gdb분석
마찬가지로 컴파일 후 간단하게 실행해보기
gdb ./file~ - gdb 분석 시작
set disassembly-flavor intel : intel 형식으로 바꿔주기
disas main : 메인 함수를 디버깅
문제에 주어졌던 0x61626364 값을 비교하는 부분인 cmp eax, 0x61626364 를 찾을 수 있다
maiin 82에 break point를 걸어준다
b *주소 - break point 설정
info reg $eax : eax 값을 확인해보면 B로 차있는게 확인됨 > 제대로 덮어씌워지는걸 확인!
0x61626364 = abcd 를 넣어본다
결과 값이 0x64636261으로 거꾸로 들어간 걸 확인할 수 있다
리틀 엔디안 방식에 다시 맞춰 dcba로 바꿔 넣어주고 레지스터 값을 확인해보면 0x61626364로 알맞게 바뀐 걸 확인 가능
'2. Reversing (리버싱)' 카테고리의 다른 글
[2024.03.30] 리버씽씽카 3주차 활동 (0) | 2024.03.30 |
---|---|
[2024.03.23] 리버씽씽카 2주차 활동 (1) | 2024.03.23 |
[2023.11.04] 리버싱 5주차 팀활동 (0) | 2023.11.10 |
[2023.10.07] 리버싱 3주차 팀활동 (0) | 2023.10.13 |
[2023.09.30] 리버싱 2주차 팀활동 (0) | 2023.10.06 |