세이프 링크는 글리벡 버전 2에 도입된 착취 완화 방법입니다 32권, 저자 이얄 잇킨
새로운 개념은 아니지만 글리벡에 적용하기까지 시간이 걸렸죠 네 안전하게 연결하면 말로크의
목록에 보호막을 덧붙일 수 있습니다 패스트빈과 치카빈이죠
네 작동법을 배우고 말록 내장도 연구해서 그걸 막는 데 유용할 거예요 그 후에
이 경감에 기반한 또 다른 2진법 기술을 개발할
거고요 , 좋아요
실행합니다 안전_link directory로 가시면 데모 바이너리와 취약한 안전_link 바이너리와 pwntools
템플릿 스크립트가 있습니다 ?????
자, 다음으로는 데모 바이너리를 GDB에 로딩해서 연결하는 안전 해부를 보겠습니다.
그런 다음 시작 명령을 발급합니다.
소스 패널의 첫 번째 줄입니다 0x20 크기의 블록 한 쌍을 요청하면 '9일까지'를
입력하고 9일까지 실행하면 됩니다
시각이 덩어리와 그 앞에 메인 스레드가 보여요
아직까진 별다른 게 없어요
다음 두 줄이 요구한 순서대로 덩어리를 풀어 줍니다
그럼 A 덩어리 옆에 놓고 다시 검사해 보죠
방금 이 덩어리를 0x20 티캐빈에 넣었습니다 이름은 pnbg라고 적혀 있죠
네 0x20 카운트 필드는 1이고 0x20 tcache빈의 헤드는 tcache 명령으로 확인된 프리
청크의 사용자 데이터에 포인터를 잡습니다 ????
청크의 주요 구역도 볼 수 있어요
2부에서 강의를 들으니 기억하시길 바랍니다
네 전에 봤던 것과 다를 게 없는데 저 포워드 포인터는 어떻게 된 거죠?
네 마지막이에요 0x20 tcache빈의 마지막 조각이죠 fd가 null이어야 한다는 뜻이에요 목록이 끝났다는
뜻이죠
대신 이상한 값이 보여요
네 PROTECT_PTR이라는 매개체의 산물로 다른 제품과 함께 REVAL_PTR을
완화 안전장치로 사용합니다
네 네 PTR_MANGLE이나 PTR_DEMANGLE이 리비오 vtable 경화제나
기능 보호 포인터를 리비오 vtable에서 사용하는 것과는 혼동하지 마세요
네 이 문맥에서 이 맥락에서 안 돼요
PROTECT_PTR이 하는 일은 마법 숫자 12로 포인터의 주소를
옮기고 xor로 포인터 값과 결과를 얻습니다
네 앞서 배운 거죠 아키텍처인 aslr에서 세분성은 중요하지 않은 12개가 고정된다는
걸 의미합니다
네 네 매크로는 계산적으로 저렴한 엔트로피를 제공합니다
핵심이죠 안 그래요?
포인터 값으로 키를 x링함으로써 일부를 암호화하는 거죠
네 네 tcache 청크의 포인터는 null이어야 하는데 주소를 갖고 있어요 12bit로
이동됐죠 xing with 0은 안 되니까요 ?
네 REVEAL_PTR은 PROTECT_PTR의 래퍼입니다 같은 작업을 다시 수행하여 원본 포인터
값을 제공합니다
B 덩어리를 티카빈으로 옮겨요
다시 검사해 보죠
0x20 티카빈 머리에 박힌 이 덩어리도 역시 손상된 것으로 보입니다
FD는 A의 사용자 데이터를 가리키죠
tcache는 메타데이터보다 사용자 데이터에 대한 포인터를 사용합니다
하지만 GDB 푸를 조금만 살펴보면 fd xrd의 주소가 12bit로 바뀌었다는
걸 알게 됩니다 원래 가치가 돌아오죠
네 이 간단한 암호화는 청크 fd에 적용됩니다 tcache빈이나 패스트빈에 연결되면요
그리고 그 덩어리가 제거되면 원래의 포인터를 회수하기 위해 역회전했죠
트캐쉬와 신속한 포워드 조작을 더는 신뢰할 수 없게 만드는 게 목표입니다
이걸 설명하기 위해 버그가 있다고 가정해 보죠 버그의 fd를 수정할 수 있도록요
자유로운 바늘을 바꾸려는 자가 있나 보죠
fd를 덮어쓰고 free훅 주소를 입력해서 할당합니다
네 문제는 새 fd가 사용 전에 REVAL_PTR macro를 거쳐야
한다는 겁니다 해독을 시도할 거예요 하지만 암호화된 적이 없으니 결과는 쓰레기일 테고 과정은
세그폴트로 갈 거예요
암호를 몰라서 포인터를 암호화할 수 없어요 케이 a 힙 ASLR 엔트로피
암호화된 fd의 바이트 중 덜 중요한 걸 덧칠하면요?
이 바이트를 Null로 처리한다고 해보죠 해독하면 이 네 글자에 주소가 나올 거예요
네 물론 정확한 위치는 이 힙이 매핑된 곳에 따라 달라지지만 여전히 다른 덩어리,
혹은 tcache에 할당할 수 있게 합니다
네 이 문제를 해결하기 위해 안전 연결 완화에는 tcache와 패스트빈 양쪽의 할당량에
정렬 검사를 합니다 무료로 정렬 검사를 하는 것과 비슷하죠
서로 다른 거시기를 쓰지만 효과는 같습니다 부분 덮어쓰기의 성공률을 낮추죠
이제 나비를 추측해야 정확한 위치를 알 수 있으니까요 안 돼!
물론 정보가 새면 보통 경감에 실패하지만 그게 핵심이죠
안 돼 네 안 돼요
안전하게 연결하면 해킹을 막을 수 있어요 유출을 막기 위해 명단을 오염시키죠
그리고... 또 1부에서 강의할 때 할당했던 것처럼 정렬이 잘못된
덩어리를 쓸 수도 없어요
전반적으로 효과적인 감축책이며 성능 간접비를 거의 증가시키지 않는다고 합니다
하지만 흠이 하나 있어요 만든 사람이 인정했죠
데모 바이너리를 살펴보면 아실 겁니다
그건 나중에 얘기하죠
네 하지만 지금은 다른 주제로 넘어가고 싶어요 제가 오랫동안 다루고 싶었던 주제죠
다중 해석
네 멀록의 행동은 지금까지 본 것과 크게 다르지 않아요
하지만 쉽게 간과되는 몇 가지 요소가 있습니다 특히 착취 경감책을 설계할 때 말이죠
데모 바이너리 디버깅 세션을 종료할 수 있습니다
이제 취약한 바이너리를 세이프_연결해서 다중 나사못 말록을 배울 거예요
실행하기 전에 평상시대로 확인하죠
체스크 체스크 말로는 우리가 보호 기능 전체와 글립코 버전 2를 다루고
있대요 네 32
GDB에 있는 바이너리를 열어 실행합니다 그러면 경고가 나타납니다
다중 스레드 프로그램을 디버깅하는 것은 도전적이죠
GDB는 이 공유 라이브러리의 버전을 찾아야 합니다 이 바이너리의 libc 버전과 일치하는 버전을요 네 상대 경로를 사용하지 않기 때문에
다음 명령을 내려서 강제로
사용하게 해야 합니다
네 그리고 경고문이 없다면 gdb는 아마 여러분의 시스템의 스레드_db 라이브러리를 사용할 겁니다 libc
버전과 일치하니까요 , 이 2진법도 연결되어 있어요 네 이건 될 수도 있지만 이 명령을 입력하라고 조언하고
싶어요 다음으로 보여드릴 건
모두 동일한 라이브러리를 사용한다는 걸 확인하기 위해서요
프로그램을 다시 돌리면 또 다른 경고가 뜨죠 안전 예방책으로 GDB는 공유 라이브러리를 로드하지
않습니다
이 명령으로 같은 디렉터리를 안전하게 표시해야 합니다
프로그램을 한 번 더 시작했지만 그는 협조할 준비가 된 것 같습니다 이런 명령을 다시 입력하는 걸 피하려면 safe_link
바이너리의 디버깅을
권장합니다 공급된 pwntools 템플릿 스크립트를 통해서요
경고와 관련된 선을 추가했습니다
다시 방송으로 돌아가 보죠 평소와 약간 다른 메뉴를 제공받습니다
네 네 새 스레드를 시작할 수도 있고요
네 상대적으로 직관적인 방법을 생각해내려고 최선을 다했지만 어떻게 작동하는지
설명드리죠
네 주요 스레드는 gdb가 그렇게 배열하니 스레드 1로 간주합니다 3개 더 시작할 수
있어요
메인 스레드에 네 , 네, 네
그럼 새 스레드를 만들어요
gdb가 알려줍니다 총 스레드 계수가 증가했지만 우린 여전히 1번 스레드 계수를 통제하고 있었죠
1번 스레드 계수
네 새 스레드를 제어하려면 옵션 5를 선택하고 바꾸고 싶은 스레드 번호를 선택하면 됩니다 ? 네, 맞아요
이제 두 번째 실을 제어할 수 있고 말록이 전부 초기화됐습니다
실마다 개수를 매겼습니다
GDB로 들어가서 후드 아래를 살펴보죠
"인포 스레드" 명령은 실행 중인 각 스레드에 대한 정보를 보여줍니다 스레드 왼쪽의 별표는 현재 어떤 스레드
GDB가 멈췄는지를 나타냅니다
이것은 중요합니다. 힙과 관련된 명령을 발동할 때 pwndbg는 스레드에 속한
힙을 사용합니다. 제가 예전에 실행한 코드 덕분이죠.
'쓰레기'를 치면 1번, a가 나옵니다 케이 a 기본 설정 힙으로 알고 있는 것이죠
이건 tcache고 이건 제가 요청한 0x20 크기입니다
프테러드 도서관에서 요청한 부분입니다 스레드 2를 만들 때였죠
네 1부로 돌아가서 제가 말씀드렸듯이 프로그램이 말로크를 호출하지 않는다고
해서 라이브러리 기능도 안 된다는 건 아닙니다
바이너리를 안전하게 연결할 때 이 두꺼비 덩어리는 이용하지 않아요
네 새 스레드 시작은 힙 메모리를 이렇게 할당할 수 있습니다 새 파일을 여는 게 _IO_FILECT를
힙에 할당하는 것과 같죠
네 그래서 스레드가 생성될 때 지정된 할당량 외에 말록이 메인 스레드가 아닌 다른 스레드에서
어떻게 반응할지 궁금해요
말록은 최선을 다해 실마다 자기만의 영역과 더미를 만듭니다
아레나를 한 번에 한 가닥씩 쓸 수 있기 때문이죠 네 스레드는 아레나를 공유할 때 서로의 할당이
완료되길 기다렸다가 자신의 것을 실행해야 합니다 그러면 동시 힙 활동이 많이
발생하면 속도가 상당히 느려지죠
바로 기본 형태의 더미처럼 경기장이 아닌 다른 더미도 말록이
처음으로 실에 묶였을 때만 나타납니다 네 재향군인청을 조사하니 추가 메모리가 매핑된 걸 알 수 있지만
각 스택과 스레드 로컬 저장소가 필요해요
이건 쓰레기가 아니에요
스레드 2 첫 할당은 요청을 계속함으로써 이뤄집니다
데이터를 적어서 라벨을 붙여도 됩니다
그 후에 재향군인회 공간을 다시 점검할 거예요
익숙한 크기의 매핑이 나타났고 그 직후에 다른 게 나타났습니다
첫 번째 매핑은 스레드 2의 새 힙입니다 gdb가 스레드 명령을 이용해 디버그 스레드 2를 디버그하도록
하면 검사할 수 있어요 그런 다음 비스라고
입력하죠
스레드 2가 있고 요청한 게 있어요
네 이 더미에 덩어리가 있어요 모두 메인_아레나 깃발이 없습니다 당연하게도 멀록에게 메인아레나에 속하지
않는다는 걸 알려주는 거죠
네 이 덩어리들이 할당되지 않은 걸 보셨을 텐데요 조금 전 매핑 시작할
때요 약간 어긋났죠
저 공간은 왜 차지하죠?
그렇군요 말록은 쉽게 이 무대를 찾을 방법이 필요합니다 스레드 2가 말록을 처음 불렀을
때 이 무대가 만들어졌죠
여기서 NON_MAIN_ARENA 깃발로 시작하는 겁니다 바로 이겁니다 깃발 세트가 풀리면
청둥오리는 아래쪽에서 시작해 더미를 찾습니다
네 새로운 힙은 특정 정렬에 매핑됩니다 시작 주소를 찾기
위해 할 일은 같은 바이트의 주소를 제거하는 것입니다
모든 비경기장 흙더미의 시작점에는 이런 힙_인포 구조가 있습니다
네 네 이 경우에는 힙_인포 스트럭트 바로 뒤에 자리하죠 네, 맞습니다
네 문제를 간단하게 설명할게요 처음엔 힙_인포 스트럭트를 가진 새 힙 다음은 아레나라고도
하는 멀록_스테이트 스트럭트예요
마지막으로 청크를 할당받을 수 있는 공간입니다
네 경기장은 여러 개를 관리할
수 있어요 그래서 이전 경기장이 고갈돼서 새로운 무대가 생겼지만 관리할
무대는 이미 다른 곳에 있는 거죠
힙_인포 스트럭션이 나오는 예지자 필드는 그때만 볼 수 있죠
이 새로운 경기장들은 위치도 다양하지만 메인 투기장과 같은 구조입니다
다중 해석의 특정 분야에 대한 미스터리를 잠시 풀어보죠
mutex는 같은 아레나에 액세스하는 스레드 간의 데이터 경주를 막는 데 사용됩니다
다음 지점은 이 과정에서 모든 공연장이 노래로 연결되는 순환 목록을 만듭니다
첨부_threads는 말 그대로예요
현재 이 아레나를 사용하는 스레드 수죠
다음 무료 양식 혼자 노래하고 고리가 없는 무료 공연장 목록 실이 없는 공연장
무료 목록에서 네 생성하지 않을 수
있는지 알아봅니다 좋아요,
네 항상 그렇듯이 기억을 되살리고 싶다면 코스
PDF에 Arena Layout 섹션을 확인하세요 ,
네 프로세스 메모리 맵으로 돌아와서 새로운 힙에 따른 이 매핑의 정체도 설명할게요
힙_인포 스트럭츠와 mprotect_size 필드를 보셨을 겁니다
읽기/쓰기로 매핑된 힙 메모리 양을 보여줍니다
알고 보니 이 지역 전체가 다 같은 쓰레기더군요
하지만 MAP_NO_RESERVE 깃발로 매핑하고 물리적 메모리를
차지하지 않도록 보호하고 있습니다 권한이 읽기, 쓰기, 실행이 없는 가상 메모리는
의미 있는 방식으로 상호 작용할 수 없기 때문입니다
맞습니다 네 서비스받기에 너무 큰 요청을 받으면 mprotect라고
불러 두 번째 구역의 권한을 변경합니다 sbrk가 기본 힙을 확장하는 것과
같은 방식으로 힙을 확장하는 거죠
그래서 가상 기억만 남겨두면 비공개 공간도 커집니다 물리적 기억만
남겨두면 안 되죠 같은 방식으로 줄어들 수도 있습니다
멀록을 조사한 결과 mp_스트럭트가 나타났습니다 tcache_count와 mmap_reshold
필드 전에 다뤘었죠
아레나_test와 arena_ max 필드에
관심이 있어요
여러분 아까 말씀드렸듯이 말록은 최선을 다해 자신만의 무대를 만들고 있습니다
경쟁력을 최소화하기 위해서죠
하지만 이런 일은 오래가지 않아요
네 아레나와 더미는 가상 메모리를 차지합니다 힙 정렬 제약 때문에 메모리는 한정돼 있죠
, 그래서
여러분 프로그램이 많은 스레드를 만드는 경우… 웹 서버가 연결을 처리하는지도 모르죠 그런 스레드는
결국 자신들의 아레나를 공유해야 할 겁니다
발생 시점은 arena_test와 arena_max에 따라 다릅니다 네 아레나_max는 예상대로 맬롭트로
설정할 수 있는 최대 규모의 아레나입니다
네 기본값은 0입니다 한도가 없다는 뜻이죠
왜 2로 바꿨는지 잠시 후 설명드리겠습니다 ,
@ 아레나_test는 여러분의 프로그램이 최대 공간을 측정하기 전에 만들 수 있는 아레나의 숫자입니다
이 테스트는 하드웨어에 기반합니다na_test의 기본값은 8이죠
공연장의 수가 이 정도 한계에 도달하면 실을 공유해야 할지도 모릅니다
그게... 이렇게 되면 말록은 모든 경기장을 돌아다니죠
주요 경기장부터요 처음이라면 다음 지점을 계속 따라가면서 음료를 가둘
곳을 찾겠죠 안 그러면 실패하면 다른 아레나의 무텍세스가 나오길 기다릴 뿐입니다
네 즉, 생성된 순서와 거의 동일한 순서로 재사용되는 광장을 보게 되실 겁니다 조작에
대한 범위가 좀 있긴 하지만요 아레나 재사용 코드는 확실히 좀 예측 불가능하거든요
네 네 그래서 이 프로그램의 arena_max 필드를 2로 설정했습니다
, 바로...
네 이렇게 하면 각자 다른 하드웨어를 갖고 있어도 아레나 공유는 아레나 2개를 만든 후에 시작할
수 있습니다
기본값보다 적지만 같은 취약점을 쓸 수 있다면 전 약간 단순화할 의향이
있습니다
말상어 퍼즐의 마지막 조각은 바로 트셰입니다
네 실마다 작은 아지트가 있다는 걸 알아요 작은 아지트가 한 덩어리 안에 존재하죠
네 시작 단계에서 토핑을 보는 건 익숙합니다 말로크에 첫 통화를 하면 토핑을
배정하기 전에 초기화하기 때문이죠
하지만 스레드가 기존의 경기장에 들어가면 말록이 공간을 만드는 곳에 스캐시를 할당합니다
네 그래서 애프터 에이스나 넘친다는 세균에 훨씬 더 취약합니다
이게 작동하는지 보죠 GDB에서 계속 새 스레드를 시작해요
새 스레드로 바꿔요
한 덩어리 요청하고 실 번호 표시해 주세요
네 다 했으면 다시 중단하고 방금 일부를 할당받은 스레드 3으로 전환합니다
앞 유리를 검사해 보니 이 가닥 앞부분에 덩어리가 있었어요
하지만 스크롤을 올리면 이 힙과 아레나를 주요 스레드와 공유한다는 게 분명해집니다
아까 할당된 양이죠 이건 힙의 시작인 tcache입니다
네 최근 배정된 배정은 맨 위 자리인데 무소속 배정 부서나 스몰빈
재분배 부서에서 배정될 수 있어요
사용해야 합니다. 이것은 우리가 활용할 수 있는 과잉 유출이나 통합 공격의 경로에 있습니다. 이것은
힙 지도의 시작점의 경계가 아니니까요.
네 지금까지 말록의 내장을 많이 살펴봤으니 그동안 본 걸 다시
살펴보고 말록의 실험실에서 실험해 보죠
다중 스레드 지원도 추가했고요
그리고 PDF의 Multithreading에서 세이프 링크 섹션도 확인할 수 있습니다
다시 이용하고 싶다면요
네 지금까지 한 것에 만족하면 안전한 바이너리를 도전처럼
다뤄 보세요 ? 네
좋아요, 잠시 후 화면을 정지할 테니 프로그램을 잘 보세요 그리고 버그를 찾으세요 좋아요,
동시성 같은 건 없어야 해요
혹시 찾으면 알려 주세요
자... 버그를 찾으면 안전 연결 완화를 어떻게 할지 고민해 보세요
좋아요 이 바이너리에서 껍데기를 벗기는 데 필요한 건 이미
다 아니까 단독으로 개발을 시작하세요
기억하시죠? 네. 명심해라 다중 스레드링을
잘 작동시키기 위해서요. 그 스크립트를 이용해
추가 조사를 할 것을 권합니다
네 잘 들으세요 이 2진법에는 4비트 엔트로피가 필요해요 100% 신뢰도에
너무 집착하지 마세요
네 곤란한 상황이 되면 여기로 돌아와서 다시 작동시켜요 그럼 옳은 방향으로 이끌어 줄게요 , 알았죠?
도청장치를 확인한 후 작전을 짜죠
GDB에 있는 바이너리를 열어서 실행할게요
지금은 한 가지만 생각합시다 경고는 무시할 수 있게요
이중 무혐의인지 확인했더니 음성입니다
제가 만든 프로그램이니 이 오류 메시지는 믿을게요
제작 소프트웨어는 꼭 재확인하세요
무보수도 안 돼요
넘쳤는지 확인해보죠
버그네요 2바이트가 넘쳤어요
버그예요 네 원시적인 걸 만드는 가장 간단한
방법이죠 그걸 우회해야 해요 ,
좋아요 이제 버그를 찾았으니 이 바이너리에서 셸을 떨어뜨리려면 뭐가 필요할지 생각해
보죠
이미 libc가 유출됐다고 가정해 보죠
네 최선의 방법은 tcache 포워드 포인터를 건드리는 거예요 프리 훅을 향하게 한다든가 그런
거요 그다음은 뭐 다 아시잖아요
물론 이제는 완화 정책의 안전장치가 그걸 보호한다는 걸 알죠
방금 요청한 0x20 덩어리를 풀어주고 빨리 감형을 검토하죠
손가락이나 포인터를 건드리는 건 안 돼요 유출할 수 있다면 문제가 안 되지만 바이너리를
안전하게 연결해야
덩어리를 읽을 수 있어서 어려울 거예요
네 아직 발견하지 못했다면 금고 연결의 약점은 바로 이 장치에 있어요
tcache 진입장은 암호화되지 않았어요
네 0x20 티카빈의 머리에 방금 풀어 준 사체의 주소가 안 적혀 있어요
네 작가는 이게 일반적인 약점이라고 했어요 이 항목에 PROTR 마크로를
적용하는 게 복잡해서요
네 이해합니다 이런 조정은
효율적일 뿐만 아니라 유지하기도 쉬워야 합니다 복잡성이 유지자에게 부담이 된다면
버그가 발생하거나
아예 입학이 안 될 가능성이 큽니다
네 tcache 자체를 조작할 수 있다면 전체와 부분 포인터 오버서티를 둘 다 수행할 수 있습니다
네 16바이트 나란히 할당하도록 가짜 덩어리를 배분하면 됩니다 그 부분은 여전히
시행되니까요
자 이제 목표에 대해 알았으니
진전을 위해 자리를 비켜드리죠
힌트를 더 원하시면 이쪽으로 오세요
이 바이너리의 pwntools 템플릿 스크립트를 살펴보죠
복사해서 편집기에서 열어 볼게요
호기심 많은 분은 스레드_db 검색 경로를 설정하세요
gdbserver를 다룰 때는 "monitor" 키워드만 추가하면 됩니다.
네 녹화 시간 add_auto_load_safe_ath 커맨드는
필요 없어요 디버깅 문제가 있다면 시도해봐서 나쁠 건 없죠
네 스크립트가 각 스레드의 말록 계정을 기록해서 덩어리에 변수를 할당할 수 있어요 지금까지
한 것처럼요 ?
이건 못 보셨길 바라요
지금쯤은 예상하셨겠지만 각 메뉴 옵션에 대한 래퍼 기능이 있어요
편집하려면 네 libc를 어떻게 유출할지 힌트를 줄지도 몰라요 마지막으로 본 곳을
기억한다면요 안 돼요
새_thread와 switch_thread 헬퍼도 그에 맞는 메뉴 옵션을 위해 있습니다
지금... 지금 지금 메인 스레드에
덩어리 두 개를 요청합니다 맞아요,
네 실 번호의 이름을 덩어리로 정했어요 글자도요 자기 걸로 바꾸셔도
돼요
이 템플릿 스크립트를 네 어떤 상태가 되는지 보자고요
해산
나사산을 확인하고요
늘 그렇듯 GDB가 스레드 1에서 우릴 멈췄어요 네 지금까지의 실험으로 스레드 1과 3이
아레나를 공유한다는 걸 정확히 말하면 알고 있습니다
기본 힙의 내용을 보기 위해 힙 명령을 발령합니다
이 조각들은 모두 실 1번 제품이에요
tcache, 2 스레드 생성 덩어리 템플릿 스크립트가 요청한 2 0x20
크기 덩어리입니다
이 조각들은 실 3번 거예요
tcache와 스크립트가 요청한 0x20 덩어리입니다
우리 목표는 단순히 스냅킨에 손대는 겁니다 네 제가 본 모든 우회로를 기록했어요 완화 담당자가
언급한 것도 포함해서요 , 스레드를 하나 선택하고 스레드 1의 tcache를
목표로 하죠
맞습니다 시작점에 가까워서 어려울 수 있습니다 그래서 현재 기술에는
극단적인 풍수지리를 요구합니다 부식 착취용 주택에서 사용한 청크를 두
배로 할당하거나
특정 프로그램 행동을 활용해야 합니다 프리 청크의 키 필드를 회피하는 거죠
다중 스레드에서는 tcache와 겹치는 게 훨씬 간단합니다
세이프_링크 바이너리에 버그를 활용해 보겠습니다 편집자 앞으로 돌아가세요
네 두 줄을 추가해 스레드 1로 갑니다 그런 다음 스레드 1의 t1_A를 편집해 사이즈
B 필드로 흘러가게 하죠 ,
그 크기를 조정해서 B 덩어리가 3번과 겹치게 할 거예요
네 prev_inuse 플래그를 무시할게요. 왜냐하면 이 덩어리는 tcache-eligable이라 체크되지 않아요.
그런 변경 사항이 있으면 GDB와 NOASLR 옵션으로 스크립트를 실행하세요
스레드 1이나 3 중 하나를 디버깅한 다음 스레드 힙을 검사합니다
네 화면 상단에 보이는 건 청크 B입니다 원래는 0x20 크기였는데 스레드 3 tcache에
겹쳐 있죠
여기서부터는 피해를 많이 줄 수 있어요 B 덩어리를 재배치하는 것도 가능해요
얼마나 쉬운지 보여 드릴게요
스레드 3의 tcache가 스레드 1의 tcache와 연결됐어요 혼란스럽죠
공간을 재분배하고 이렇게 쓸 수 있어요
네 스레드 3은 이제 엉망진창이 됐습니다 하지만 가비지 데이터 대신 유용한 걸 쓸 수 있죠 ,
여기에요
더 나아가려면 그 껍데기를 얻으려면 libc 정보가 필요해요
이미 경험이 있으시니 어떻게
진행할지 결정해 주세요
어떻게 했는지 궁금하면 다시 와서 재생시켜요
바이너리 연결 금고에서 libc 주소를 어떻게 유출했는지 보여드릴게요 화면에 제 스크립트가 있어요
우리 강의 자료에서 복사본을 다운로드할 수 있어요
양식 번호 2라고 적혀 있어요
지금 커서가 있는 곳까지 스크립트는 이전 템플릿과 거의 동일합니다 네 2번과 3번 분량이 시작됐어요
2번 분량은 실 1번과 실 2번 분량이에요 ? 네
네 이번에는 메인 아레나를 스레드 1과 공유하는 스레드 3에 0x240 크기의 덩어리를 할당하고 가드 덩어리를
배분합니다 ?
네 이 미끼는 크기도 꽤 유연해요 왜 이걸
골랐는지 알려드릴게요
네 그런 다음 다시 오버플로를 사이즈 필드로 옮깁니다 아까
한 것처럼요 그리고 스레드 3뿐 아니라 다음 0x240도 겹치게 합니다
네 그러면 tcache 캐시 크기 제한을 넘어섭니다 그래서 prev_inuse 플래그를 설정합니다 풀었을 때 뒤로 통합되는 것을
방지하기 위해서요 거기서
그래서 가드 토크가 생긴 거예요
네 네 pwntools의 정지 기능을 이용해 여기서 멈추죠 디버그할 기회를
줍니다 ?
일시 정지를 추가하고 나면 일반적인 옵션으로 템플릿 스크립트를 실행합니다
키를 누를 때까지 일시 중단합니다
입력하는 건 별로 유용하지 않지만 여기선 잘 작동해요
GDB로 들어가서 스레드를 디버깅하고 힙 명령을 발령합니다
네 이 무정부 공간에서 b가 시작됐어요 이 공간이 b와 스레드 3 tcache, 그리고 우리가
할당했던 0x240 크기의 공간을 포함해요
네 첫 번째 템플릿과 같은 시나리오예요 B 덩어리가 전보다 커졌을 뿐이죠
그래서 체감하지 못하고 무감각한 상태로 풀려났죠
이제 네 특정 위치에 대한 정리가 안 된 bin 메타데이터를 쓰기 위해 나머지를
사용했었죠 안 됩니다,
우리가 할 수 있는 게 바로 그거예요
네 B 단위를 다시 정리하면 정리가 안 된 빈 fd와 bk를 스레드 3 tcache에 써서 두 개의 진입로를 겹치게
할 수 있어요 ,
세이프 링크를 우회하는 건 이 정도입니다
네 그 후에는 아레나에 할당될 수 있습니다 이 경우에는
tcache를 통해 주 아레나에 할당될 수 있습니다 힙 주소를 유출하지 않고요
네 물론 우리가 폭탄을 투하하려면 아직 할 일이 더 있죠 libc 유출부터요
그러려면 더러운 파일 스트림을 조작해야 해요
네 안타깝게도 우리가 카드를 쓸 주요 경기장과 스트우드_IO_write_base
필드는 tcache가 기본적으로 차지할 수 있는 범위보다 넓어요
네 남은 부분을 분류해서 불량 할당을 더 위협적으로 만들 수 있어요
3번 스레드를 라지빈으로 겹쳐 놓고요 GDB를 닫고 템플릿 2로 돌아가서 어떻게 하는지 보겠습니다
추가한 일시 중단을 제거하고 여기에 하나를 놓습니다
이 선은 방금 본 스레드 3의 정돈되지
않은 부분을 유지합니다
네 두 가지를 할 수 있어요
먼저 tcache를 겹쳐 놓은 덩어리를 제어합니다 잠시 후에 tcache에 카운트 필드를 설정할
거예요
글리벡 2를 기억하세요 네 32살 이후 말록은 적절한 개수 필드가 0보다
크지 않으면 안 해요
두 번째로는 재구성 프로세스가 됩니다 정돈되지 않은 포인터를
앞 뒤로 적습니다
이 덩어리의 크기는 어떤 tcache 엔트리를 작성할지 결정합니다 네 네 대규모 참가자를 공략하고
싶어요 예를 들면 0x400
같은 거요 네
네 네 하지만 0x40과 0x50은 libc 유출에 관련된 모든 오염원을
조작할 수 있을 만큼 크죠 ?
왜 이렇게 했는지 곧 알게 되실 겁니다 하지만 아시다시피 계획대로 되지 않을 겁니다
네 우리가 tcache에서 가장 큰 부분을 할당해도 0x410으로 충분치
않아요 정리가 안 된 공연장과 광대를 잇기엔 부족하죠
맞아요 이를 해결하기 위해 정돈되지 않은 손가락 끝을 냄새에 가깝게 조정할 수 있습니다 남은 부분을 라지빈에
분류하면 되죠
0x440 라지빈을 골랐어요
이제 이해가 좀 됐으면 좋겠네요
네 B 덩어리를 0x4f0 크기로 만들었는데 0xb0 크기로 다시 요청해서 0x440
덩어리가 남아요 제가 노리는 라지빈 크기죠
잘 들으세요 저희가 분류하려는 덩어리가 이미 라지빈의 마지막 잔여물이에요
즉, 정리가 안 된 덩어리가 라지빈보다 작은 걸 요청하면 즉시 잔여물이 되죠
PDF에 있는 무체계 차트를 확인하세요
네 0x440보다 더 많이 요청하거나 0x400과 0x430 사이의 다른 걸 요청해도
돼요
어느 쪽이든 0x440 덩어리는 적절한 라빈으로 분류될 겁니다
네 네 전부 탈진시켜서 할당해 PDFs에서 기억을
되살릴 수 있는 기능을 요청했죠 , 재고 정리
부분
네 멈추기 전에 마지막으로 할 일은 스레드 3 tcache의 첫 부분을 겹치는 0xb0 크기의 덩어리를
써서 0x40 카운트 필드를 0보다 높게 설정하는 거예요 그럼 0x40 tcache빈의 가짜 덩어리를 할당할 수
있죠 , 좋아요
일반적인 옵션으로 스크립트를 다시 실행해 보죠
해산
스레드 3으로 바꿔
디폴트 힙의 관련 부분을 검사합니다
네 여기 스레드 1에 있는 첫 번째 청크가 시작되고 그 후에 수정된 청크가 스레드 3과 겹쳐집니다
네 네 tcache 0x40 카운트 필드를 2로 설정했어요
여기 보이죠 ,
네 이건 나머지예요 0x440 라지빈으로 분류한 거 기억하죠? fd와 bk의
가치를 높이려고요 ?
네 네 pnbg의 tcache에 따르면 스레드 3의 tcache는 이제 두 배의 개수를 세고 있고 주 경기장을
겹치는 10x40 크기의 덩어리가 있습니다
네 라지빈을 사용하는 것에 대한 보너스로 tcache에 몇 가지 포인터를 더 드릴 수 있어요
라지빈 nextsize 포인터 형태로요 물론 이 이용에서는 이용하지 않겠지만요
이제 스타우트를 손볼 준비가 됐어요
하지만 아직 공격 범위 안에 들어가지 않은 걸 아실 겁니다
네 네 ,
네 인정합니다 마지막 셋업으로 건너뛰었어요 안 돼요 내가 libc를 유출한 건 주요 공연장과 스타우트 사이의
간극을 확실히 이을 수 없었기 때문이야
여기까지 온 당신도 마찬가지였을 거예요
두 구조물 사이에는 데이터가 많지 않습니다 이 프로그램을 통해 거의 모든 구조물을 안전하게
부술 수 있습니다
예외는 이 사분자입니다 프로그램 메뉴에 숫자를 정수에 입력하고
가독성 메모리를 가리키도록 변환하는 데 사용됩니다
네 이런 문제를 피하기 위해 입력 처리 방식을 바꾸는 것도 고려했지만 때로는
다른 글립코 기능이 방해될 수 있다는 걸 알아두세요
네 네 제 대안은 스레드 3 tcache로 할당된 나머지 부분을 편집하는 거예요 가장 덜 중요한
두 바이트를 전이된 라지빈 fd로 수정하려고요
네 이렇게 하면 스트우드에서 0x40 티카체빈 입구를 찾을 수 있어요 이제 그것과 메인 경기장
사이의 간격을 메울 필요가 없다는 뜻이죠
그렇습니다 부식의 집에서 배웠듯이 여기엔 4비트 엔트로피가 필요합니다 그래서 0x440
라지빈을 선택했죠 안 그러면 정리가 안 되니까요
보세요 5번째로 덜 중요한 나비가 스트라우트의 주소와 일치해요
네 이건 우리 착취 성공률을 약간 높이는 불행한 libc 부하 주소를 보장해줘요
꼭 필요한 건 아니에요 남은 건 그냥 혼란 속에 두고 모험을 할 수도 있었어요
불량 배분을 경기장 끝으로 옮기는 방법을 보여드리고 싶었어요
템플릿 스크립트로 돌아가보죠 여기서 이 단계를 마무리할 겁니다
추가한 일시 정지 대사부터 삭제하세요
t1_d 청크는 tcache 진입경로예요 이 선은 이 부분에 적습니다 바이트가 덜 큰 두
바이트를 덮어쓰고 남은 라지빈 fd를 가리키죠 , 스트라우트를 가리키려고요
네 네 제 플랫폼에서 ASLR이 꺼지면 0으로 설정해둔 거죠 그러니 디버깅할 때마다
원하는 결과를 볼 수 있습니다
GDB가 고른 플랫폼 주소와 일치하도록 이걸 바꿔야 할 수도 있어요
네 이 단계에서 아스라 나블을 제대로 맞혔다면 스레드 3의 tcache는
먼지 덩어리가 겹쳐 있을 겁니다
스크립트의 나머지 일은 그 덩어리를 할당하고 libc 유출을 준비하죠 최적화 챌린지에서 한
것과 똑같은 방식으로요 프로그램이
인쇄하면 메뉴가 libc 유출을 잡아냅니다
스크립트를 GDB와 NOASLR 옵션으로 실행해서 확인을 할 수 있습니다
왜냐하면 스타우드 주소지에 있는 ASLR 니블에 대한 내 추측이 GDB가 고른 것과 일치하거든요
aslr이 작동을 안 하면
다 순조로울 거예요
낭종이 누출된 것 같아요 청새리 한 마리가 이 일에 엮여 있고요
네 정보부로 전환하죠 재향군인회 공간을 조사한 결과 libc 유출은 정확해요 ? 네
네 덕분에 우리가 유리해요 libc 정보가 새는데도 바로 편집할 수
있죠
그럼 난 이만 가서 등껍질을 던져서 이 일을 마무리하죠
더 이상 걸림돌은 없을 테니 쉽게 끝내면 좋겠어요 영상 복구 끝나면 최종
취약점을 검토하죠
이번 도전의 솔루션 스크립트를 살펴보고 있습니다
중단되기 전에 마지막으로 한 일은 libc를 유출한 거예요
마지막 단계는 간단합니다
이미 스레드 3은 중복으로 통제 중이고 libc가 유출됐어요
됐어요 스레드 1로 다시 전환했어요 거기서 tcache에 겹치는 덩어리를 편집할
수 있죠 고리의 주소를 0x40 tcache빈에 적었어요
그런 다음 네 안 돼요!
네 이제 글리브의 시스템 기능에 고리를 걸고 명령줄을
풀기만 하면 됩니다
네 네 4비트 엔트로피로 추측했기 때문에
100% 신뢰할 수 없거든요 ,
생산 조건에서 착취를 진행하면 몇 번
시도한 후에 껍데기를 얻을 수 있어요
마일리지가 다를 수 있어요
아무 도움 없이 바이너리 링크를 이용한
건 축하해요
그 외에는 뭔가 배우셨길 바랍니다
8개의 할당만 있었어요 스레드 2 아레나를
만든 것까지 포함하면 9개죠
더 효율적으로 혹은 100% 신뢰할 수 있게 된 거라면 어떻게
했는지 듣고 싶군요
아마 보셨을 거예요 '사제가 선생님이 되다' 안내 방송요 학생들이 가르쳐 준 멋진 것들을 보여
주거든요
이제 이번 시간에 배운 내용을 정리하면서 마무리해 보도록 하겠습니다
글리벡 버전 2에 나온 안전장치 완화법을 먼저 알아보죠 32 ASLR 엔트로피를 이용해 tcache와
패스트빈 포워드 포인터를 암호화하는 법 덩어리 정렬을 강요하는 법
안전 연결은 개발자를 압박해서 정보를 유출하게 하는 거예요 말록의 링크 목록을
조작하기 전에요
네 대부분의 경감 요인이 그렇듯 해커들이 인내심을 잃거나 유용한 원시적 프로그램을 만들
수 없게 되거나 추가적인 장애물을 통과해야 해서 소프트웨어 관리자들이 취약점을 패치할
시간이 늘어나길 바랍니다
또한 안전한 연결이 트캐쉬나 패스트빈 링크 리스트를 보호하지 못한다는 것도 알게 됐죠
그래서 트캐시가 특히 취약합니다 더미 위에 있기 때문이죠
할 수 있습니다 싱글 스레드 프로그램에서 메인 스레드 tcache는 디폴트 힙의 시작에 있습니다
조작을 어렵게 만듭니다
하지만 다중 스레드 프로그램에선 tcache가 어느 곳이든 할당될 수 있습니다
그래서 여러 나사로 나뉜 환경에서 말록의 행동을 처음 보는 새들에겐 더
취약해 보입니다
네 tcache와 컨트롤 할 때 두 바이트 버그를 이용했습니다 tcache의
진입 영역에 재분류를 통해 arena 주소를 썼습니다
이 정도면 충분한 정보를 유출하지 않고도
금고 연결을 막을 수 있어요
libc 주소를 유출해서 정보를 흘린 겁니다
네 네 민감한 데이터를 공격하지 않으려면 4비트 엔트로피가
필요하죠 ? 네, 그렇습니다
그래서 그 추측을 좀 더 신뢰할 수 있게 라지빈을 앞뒤로 써서 티케시에 포인트를
적었어요 정돈되지 않은 포인트를 적는 대신에요 후크를 덮어써서 껍데기를 얻었고요
이번 강의의 리소스에서 제 솔루션 스크립트를 다운로드 받을 수 있습니다
네 안전 연결 완화를 다시 상기하고 싶다면 코스 PDF에 기록돼 있어요
네 멀티 스레드 울록을 실험하고 싶으시다면 울록도 새 스레드를 시작해 스위치를
바꿀 수 있습니다 세이프_링크 바이너리처럼요
명심하세요 템플릿 스크립트를 사용하지 않을 경우 이 강의 초반에 GDB가 다중 스레딩에서
잘 작동하는지 확인하기 위해 사용한 두 개의 명령을 입력해야 합니다
PDF에 문서화되어 있어요
글리벡 2를 조심하세요 34명이 dso로 옮겨서 rthread 기능을 리bc dso로 옮겼는데
안타깝게도 기록 당시 gdb는 이런 걸 감당할 능력이 없었어요
글립비크 2호와 연결할 때 새 실을 연결하지 않으면 괜찮을 거예요
34개입니다.
하지만 다중 스레드 디버깅이 동작하기를 기대하지 마세요. 아주 최근 gdb 빌드를 사용하지 않는다면요.
네 다음 영상에서는 오랫동안 이론화되어 왔지만 최근에는 소프트웨어에만
사용된 기술을 알아보겠습니다