부식의 집 3번째이자 마지막 프리미티브는 꽤 복잡합니다
네 혹시 힘드시면 걱정 마세요 솔직히 이건 이론적으로 가능한 걸 알아보는
연습에 가깝죠
글리벡 변수를 다른 곳으로 이식할 때 사용돼요
쉽게 설명해 드리죠
글로벌_맥스_패스트부터 변질시키는 거죠 무체계 빈 공격으로요
그리고 많은 부분을 풉니다 원시적인 것을 실행하고 소스 변수에 힙 주소를 씁니다
네 그렇게 하면서 소스 변수는 힙에 복사됩니다 원하면 이 기회를 이용해 그걸 조작할
수 있죠 ? 네
네 이 시점에서 큰 부분을 할당하면 원시적인 2가 발생해 소스 변수를 대체합니다 안 돼요
하지만 그 덩어리를 다른 패스트빈 슬롯에서 할당한다면요? 그 결과 소스 변수가 완전히
별개의 변수로 "이식"되는 거죠
네 이건 한 함수 포인터를 다른 함수 포인터로 복사하는 데 사용됩니다 그럼 덜 중요한
두 바이트의 함수 포인터를 수정할 때보다 실행을 더 멀리 리디렉션할 수 있죠
이 원시적인 기계는 강력하지만 만들기가 어렵습니다
성공하려면 뭐가 필요한지 생각해 보죠
가장 큰 문제는 목적 변수가 이식에 필요한 부분을 가리켜야 한다는 거예요 패스트빈
슬롯에서 할당하면 이전 데이터를 대체할 수 있거든요
원시인이 도와줄 수 있는데 문제가 있어요 네 이걸 떼어내야죠 목적 변수에 주소를
쓰려면요 하지만
공짜인 동안 두 번째로 떼어내 소스 변수를 히프에 복사해야 합니다
물론 이 프로그램엔
없는 버그죠
네 하지만 더 나은 버그를 활용해 다른 버그를 만들 수 있고 애프터 무삭제를 더블 무삭제로 바꿀
수 있다는 걸 배웠어요
여기서 복잡해지기 시작합니다
스크립트를 만들어 우리가 하려는 걸 시각화하도록 하죠
화면이 시작점입니다
이 강의 리소스에서 이 스크립트를 다운로드해 템플릿 2를 따라 하세요
보시다시피 이전 비디오에서 쓴 걸 일부 차용했어요
여기서 방향 감각을 잃은 맹인 공격도 있죠
네 우리 목표는 프림티브 3을 활용해서 2부에서 소개된 모어코어 훅의 가치를
stderr vtable 포인터에 이식하는 거예요
네 이 동작은 그 자체로는 쓸모없지만 실행 가능한 메모리로 포인터를 이동하는 건 가능합니다
데이터로 가는 포인터를 갖고 있던 위치로 말이죠
오히려 성공 여부를 확인하는 게 더 쉽죠
네 초기 3단계 각 단계가 주석으로 달렸고 지금은 자리 표시자 편집 레이블이 있죠 곧 우리 고유의
코드를 추가할 겁니다 ????
네 네 , 이 스크립트는
2부에서 풍수를 다뤘는데 이번에도 마찬가지입니다
'tmp'와 '접합'이라는 두 덩어리를 요청했어요
탬퍼의 색인을 저장합니다 해방된 후에도 우리가 쓸 수 있는 지식에요 , 이 지식은
두 덩어리가 풀리면 맨 위 덩어리와 하나로 뭉칩니다
tmp보다 16바이트 큰 세 번째 덩어리가 할당되죠
네 좋아요 이제 이식 부분을 할당하면 사용자 데이터와 일치하지 않고 크기
필드와 일치해요
이 프로그램은 10 바이트까지 쓸 수 있기 때문에 바이트가 덜 큰 두 바이트를
조작할 수 있습니다
네 이식할 송아지를 두 개의 빠른 칸에서 빼낼 거예요
그래서 크기를 확인하기 위해 중간 크기를
바꿀 거예요
물론 애프터서비스 버그가 넘쳐나는 버그였다면 훨씬 쉬웠을 겁니다
하지만 우린 하드 모드로 플레이해요
제가 설명한 건 전부 이 대사로 한 거예요
그럼 '이식'이라는 표식이 남죠 그 표적이 글리벡을 잡아서
이동시켜야 해요
종이로 크기를 조절할 수도 있어요
이제 더블프리를 만들 준비가 됐어요 네 방법은 두 가지예요 예를 들어
두 덩어리를
겹치는 풍수를 더 만들 수도 있어요
하지만 다른 방식으로 진행하죠 패스트빈 메타데이터를 직접 조작해요
어떻게 돌아가는지 최선을 다해 설명할게요
이식 부위의 크기가 0x20이에요
여기 있어요
'잃어버린'이라고 적은 부분을 요청할 거예요
왜 그런지 잠시 후에 보시죠
목적지 크기만 한데요
저희는 0x1630으로 하겠습니다
0x1630
이때 혼란스러운 공격이 시작되죠 대본은 이미 해결했어요
네 그다음에는 애프터서치 수정본을 써서 풍수를 이용해서 이식한 파편의 크기를
잃어버린 파편에 맞게 바꿀 거예요
목적지 크기의 덩어리 두 개가 겹쳐져 있습니다
메모리 다른 곳에 목적 변수가 자리잡고 있습니다 우리 경우엔 stderr의 확실한 포인터입니다
파일 스트림의 주소가 vt가
가능합니다
네 이 변수를 이식할 주소로 채우려는 거죠 이 덩어리를 할당하면서요 이 덩어리를요
이걸 하려면 잃어버린 부분을 풀어야 합니다 원시적인 1을 작동시키고 목적 변수에 주소를 적습니다
네 그리고 원래 목적지 값을 갖는 fd도 얻습니다 하지만 신경 쓰지 마세요
이식받은 청크를 풀어줘야 해요
크기가 같아서 같은 통에 연결됩니다
fd도 나오는데 이번엔 빠진 부분을 가리키죠
여기서 마법이 일어나죠
네 네 그 덩어리를 가리키죠 네, 맞아요,
ASLR 엔트로피를 추측하지 않고도 이 작업을 할 수 있습니다 라이브러리처럼 힙은 전형적으로 페이지 정렬이
되어 있거든요
네 그래서 이식 수술을 원래 크기로 할당되지 않고 0x20 크기로
시작한 겁니다
그럼 두 덩어리가 충분히 가까이 있었다는 뜻이죠 둘 다 꽤 큰데도 주소 공간
값 한 바이트만 분리돼 있었어요
필요하다면 목적 크기 둘 다 할당해도 되지만 그러려면
4비트의 ASLR 엔트로피를 추가로 계산해야 하는데 전 그러고 싶지 않아요
네 네 이중으로 진행되지 않는 시나리오가 돼요 우리가 계속
원했던 거죠
물론 잃어버린 덩어리는 이제 없어졌죠
무료지만 말로크가 언급한 적이 없어서 재활용이 안 돼요
네 이제 이식받은 인체를 나머지 공격에 할당해 줄 수 있어요 소스 변수를 확보하는
거죠
네 하지만 목적지 패스트빈에 포인터가 남게 되므로 나중에 안전하게 다시
할당할 수 있습니다
받아들이기 힘들었을 거예요
이 원시적인 것을 스크립트하고 단계적으로 살펴볼 것입니다
잃어버린 청크부터 요청하죠
목적지에 맞게 커야 해요
네 그 후에는 혼란스러운 발작은 대본에 처리됐으니 이식 부위를
잃어버린 부위와 일치하도록 바꾸면 돼요 16개의 바이트가 일치하는 편집이기 때문에 사전에
안쪽 표시를 하나 해야 합니다
기억하세요, 덩어리가 둘 다 특정 크기와 큰 크기가 돼야 해요
하지만 가깝게 지내길 바라죠
그래서 이 지점이 됐죠
같은 크기로 겹쳐진 두 덩어리죠
네 그다음 잃어버린 부분을 꺼내고 이식할 부분을 이식한 다음 후자의 fd를 건드려서
다시 본래대로 돌려놔요
자유롭게 길을 잃죠
무료 이식
편집 이식도 하고요
여기서 1바이트만 쓰면 되니까 p8으로도 충분합니다
어떤 가치를 써야 할까요?
네 그렇군요 이식받은 청크의 주소가 뭐가 될지는 아직 몰라요
하지만 계산할 수 있죠
0x 뭐시기부터 시작해요
1,000
메인 아레나를 쓸 거예요 메인 스레드의 첫 번째 조각이죠 글리벡 버전 2를 쓰고 있어요
27
tcache 청크는 0x250 바이트고요
그다음은 0x430 크기예요
이제 이식할 환자 차례입니다
0x250 더하기 0x430은 0x680
네 네 0x6a0을 가리키죠 그러니까 가장 덜 중요한 바이트를
0x80으로 교체하면 돼요
네 이식할 장소가 0x10 같은 더 낮은 곳이었다면
할당량을 정해서 위치를 바꿀 수 있어요 기존의 덩어리의 크기를 바꾸거나
글리브의 도움으로 시작 지점을 바꿀 수도 있죠
libc가 어떤 상태인지 보죠
GDB 옵션으로 스크립트를 실행합니다
글리벡이
중단하래요
이건 안 좋은 주소에서 물건을 싣는 세그폴트와 달라요 libc
로드 주소 엔트로피가 가장 적게 나오는 건 3, 4가 아니에요
다른 문제인 것 같아요
pwndbg의 k 명령을 이용해 더 상세한 역추적을 프린트할 수 있습니다
이식받은 아기를 꺼내려다가 문제가 생긴 것 같아요
우리 계산에 따르면 주소는 0x680이었습니다
동봉한 오류 메시지입니다
네 패스트빈의 계산서에 문제가 생긴 것 같아요 2부에서 영혼의 집을 배우면서
그 문제를 겪었죠
잘 들어요 이렇게 하면 풀려난 돼지에게 정신 감정을 할 뿐이에요 ? 네, 맞아요
현재 그 위치의 크기 필드는 0이에요 그래서 확인을 안 하는 거죠
청크의 크기를 이식해서 차세대 크기가 없어요
물론 정확한 크기는 우리 착취에 중요하니 바꿀 수 없죠
하지만 간단한 풍수로 해결할 수 있습니다
위쪽 덩어리로 새 장을 만들 거예요
문제는 이거예요
이식할 부분은 0x20 크기로 시작해서 여기부터 확장돼요
네 하지만 기록 삭제 버그로 크기를 바꾸면 말록은 다음 구역이 여기라고 생각할 거예요
사라진 덩어리의 끝에서 조금 떨어져 있죠
네 아직 아무것도 안 썼어요 그래서 null이죠 그래서 Nextsize check가 실패하는 거예요 ?
이 새로운 분야를 정상화하려면 몇 가지 방법이 있습니다
예를 들어, 데이터를 그냥 사라진 부분에 쓸 수도 있죠
이 특정 프로그램으로는 불가능하지만 다른 시나리오에서는 가능할 겁니다
네 이식 수술을 하면서 사라진 부분의 크기를 바꿀 수도 있어요 그럼
다른 덩어리로 쓰기 쉽겠죠
하지만 지금 상황에서 가장 효과적인 해결책은
이겁니다 이식할 골수를 할당받고 골수를 잃었지만 앞으로 더 큰 돈이 어디서 나올지
알아요
네 이제 우리가 할 일은 윗부분을 충분히 줄일 수 있도록 요청하는 거죠 그 크기 필드가 미래의 nextsize
필드에 쓰일 수 있도록요
그 덩어리를 빼내고 계속 진행할 수 있어요
네 흔적얼록 메타데이터는 확인되지 않았으니
우리가 건드리지 않으면 원래 크기는 그대로예요
다음 사이즈가 확인 사격을 할 때 통과해야 합니다
이 작업을 구현하는 건 아주 간단합니다
편집기로 돌아가 간단히 해보죠
여러분 덩어리를 더 할당하고 풀기 전에 방금 말씀드린 것과 비슷한 일을 이미 했다는
걸 기억하세요 이 공격의 풍수지리 단계에서요
네 이식할 덩어리와 일치해요 크기가 임의로 정해져 있죠
네 0x420을 고른 건 현재 tcache와 연결할 수 있는 가장 작은 덩어리이기 때문이에요
네 이식한 부분과의 작은 차이 때문에 목적지 사이즈를 16으로 변경하면
슬라이드에서 본 결과가 나올 거예요
네 제일 큰 덩어리를 검사할 지점에 표시해 두고 나중에 이식할 덩어리를
빼낼 거예요
작은 변화를 주고, GDB 옵션으로 스크립트를 다시 실행합니다.
이번엔 중단하지 않습니다
그럼 목적지 패스트빈을 살펴보죠
더블 프리로 가는 게 목표라는 걸 명심하세요
이 포인터 표시가 이식받은 사람을 가리키고 있어요
그 덩어리가 자신을 가리키죠
더블 프리, 적어도 그 결과인 쓰기 애프터 버그를 강압적으로 사용했습니다
네 이제 이식할 덩어리를 다시 넣을 수 있어요 목적지에서 주소를 제거하지 않고도요 패스트빈
슬롯에서요
네 네 이식 예정지에 있는 이식체를 마지막으로
할당해야 해요
편집기로 돌아가 원시 3을 마무리하죠
일이 좀 복잡해져도 걱정하지 마세요
다음 수업 전에 배운 걸 이 영상 마지막에 정리해 볼 거예요
이제 소스 값만 잡으면 됩니다
그게 default_morecore 함수의 주소입니다 우리 경우에요 목적지에 적어요
이식받은 청크를 다시 줄 거예요 곧 빼내야 하니까요
이식 라벨 업데이트하는 거 잊지 마요
네 그다음 이식할 덩어리의 크기를 바꿔야 해요 그래야 분리할 때 원시적인 1을
시작으로 우리 원본 값이 fd에 복사되죠
크기가 변형되면 이식한 부분을 분리해서 그 기능을 하게 하는 거죠
네 계속하기 전에 무료로 진행하려면 패스트빈 nextsize 체크를 통과해야 해요
그래서 통과하려면 대본 시작 부분에 약간의 풍수를 추가해야 하죠 안 돼요, 안 돼요
네 다시 한번 가장 큰 덩어리를 그 자리에 적고 있어요 이식할 덩어리의
크기와 일치하는 지점을 찾아야 합니다
네 마지막 풍수를 추가하고 나면 이전 편집본을 다시 보세요 무료 호출입니다 ,
이제 원시적인 2단계로 접어들었어요
좋아요 버그를 이용해서 원가를 수정할 수 있어요 이식한 부분을
수정된 값으로 되돌리는 거죠
네 하지만 프리지티브 3으로 그 가치를 다른 곳으로 옮기는 게 목표입니다 그래서 더블프리가
필요하죠
네 지금 목적지 크기를 요청하면 목적지 패스트빈에서 이식할
부분을 fd-원래 값이 그 안에 복사됩니다
네 이제 이식할 부분을 원래 크기로 되돌려서 패스트빈 크기를
확인한 다음 이식하면 돼요
스크립트를 마지막으로 수정해보죠
준비되면 초기 3가지가 잘 동작하는지 봅시다 GDB 옵션에서 스크립트를 실행합니다
다 잘 됐고, 불운한 libc 부하 주소만 안 나오면 프로그램은 안정될 거예요
목적 변수를 부수고 검사합니다
스트림 vtable stder의 vtable 포인터입니다 파일 스트림 vtable을 가리키는 대신 지금처럼요 default_morecore
함수를 가리킵니다
네 초기 3단계로 글리벡 변수를 다른 장소로 성공적으로 옮겼어요
주소도 유출되지 않았고요
넘어가기 전에 초기 설정 3을 간단히 요약해보죠
우리 목표는 코어 훅의 가치를 스티더 vtable 포인터로 옮기는 거였어요 네 말씀드렸듯이 이 자체로는 쓸모없지만
몇 가지 구성 요소를 사용하는데 다음 비디오에서 중요해질 겁니다
그리고 풍수를 좀 더 활용했어요 덩어리를 할당해 애프터서피드를 맞추고
나중에 덩어리 크기에 손을 댈 수 있게요
네 기억하세요 이 부식 바이너리는 10바이트까지만 쓸 수 있습니다 따라서 바이트가
가장 적은 두 바이트만 사용할 수 있죠
네 그리고 모래알 메타데이터를 더 많이 기록했어요 특히 덩어리
크기로요
네 잠시 후 잠시 후
?
그다음에는 이식을 요청했는데 덩어리가 빠졌어요
네 잃어버린 덩어리는 이중으로 안 나오게 해 주고 이식하면 원천을
목적지로 옮길 수 있어요 패스트빈 슬롯이죠
네 덩어리를 가까이 할당해야 필요한 이상의 ASLR 엔트로피를 추측하지 않아도
됩니다
그래서 이식할 덩어리의 크기가 0x20밖에 안 되는 거예요
그 다음은 익숙한 방향 감각 상실 공격입니다
네 성공하면 global_ max_ Fast 변수에서 큰 값을
씁니다
네 무체중성 빈맥이 오면 서기 애프터미드로 이식 대상
치수를 조절할 거예요
이식한 것과 유실된 건 목적지 크기예요
그러니까 우리가 풀어 주면 말록이 퍼스트빈 틈에 연결해서 목적지를
연결할 거예요 스티더 vtable 포인터요
여기서 더블 프리 시나리오를 짜야 해요
네 먼저 잃어버린 환자를 구하고 이식받은 환자를 목적지로 옮긴 다음 애프터서치
키를 써서 fd를 제자리로 돌려놔요 ? 네
네 그래서 이 덩어리를 서로 가깝게 할당하면 편리해요 fd 한
바이트만 이렇게 수정하면 ASLR 추측을 피할 수 있으니까요
네 이식할 부분을 다시 이식할 수 있는 상황이 됐습니다 곧 다시
빼내야 하니까요 이식할 부분을 목표 지점에 두는
동안에요
네 이식할 덩어리의 크기를 원위치로 바꾸고 다시 풀어 줘서 원위치를
이식할 fd에 적었어요 ? 네
됐어요 드디어 드디어 원래 크기로
할당받을 수 있죠 ?
초기 버전 2가 호출되었습니다 변경된 소스 값을 목적 변수에서 복사합니다
이건 기본 3단계예요 원하시면 강의 자료에서 스크립트 예제를 다운로드하세요
우리가 수행한 작전 중 가장 복잡한 작전 중 하나라는 건 압니다
이 정도 통제가 비현실적이라고 생각하신다면 부식이
발생한 이진법의 집을 원시적인 3번 없이도 이용할 수 있습니다
나중에 배우면 돼요
네 하지만 지금은 프리미티브 3이 어떻게 작동하는지 알아두세요 다음 영상에서는
코로식 프리미티브를 모두 사용해 바이너리의 껍질을 벗길 테니까요