네 이 영상의 목적은 두 가지입니다 먼저 tcache 메커니즘을 배워 보죠 'tcache 덤핑'이라고
해요 그럼 tcache 첫 공격인 경감에 대해 알아보죠
tcache_dup_2로 검색하세요 31 디렉토리입니다 데모 바이너리를 보실 수 있습니다
바로 GDB에 저장하죠
평소처럼 메인 함수에 중단점을 설정하고 프로그램을 실행할 겁니다
네 일단 멈추면 명령어를 보면 이 데모는 'GLIBC 버전 2'를 사용하고 있어요
31
마지막으로 다뤘던 버전은 2편이었어요 28
네 소스 패널을 보면 데모 바이너리에 평소보다 더 많은 일이 벌어지고 있네요 하지만
특이한 건 아니에요
이 선들은 가로세로 20cm 크기의 덩어리 14개를 요청하고 있어요
이 루프를 통과하는 대신 반대편에 중단점을 설정하죠
필요 없는 유용한 GDB 기능을 계속해서 소개하고 있습니다 'tb'로 일시
중단점을 설정할 수 있습니다
네 네 10번 라인에 임시 중단점을 설정하고
계속하겠습니다 ,
'비스 1'로 첫 번째 부분만 검사합니다
이건 tcache입니다 크기 좀 보세요 0x290, 2보다 크죠 아까 비디오에서 본 28 tcache는
두 개의 너비 카운트
필드의 부작용입니다
'전시 15'로 15개를 검사하세요
기본값은 10인데 그보다 더 많이 할당했어요
네 tcache 외에도 루프가 요청한 14개의 덩어리가 보입니다 아직까진 별다른 게 없네요 ?
네
'컨텍스트 코드'를 이용해 프로그램이 뭘 하는지 보세요
또 다른 루프입니다 이건 이전 루프에 할당된 14개의 덩어리를 자유롭게 합니다 요청한 순서대로요
이 루프를 실행해 중단점을 설정합니다 임시든 아니든 13라인에, 그리고 계속합니다
다시 한번 '시각 15'로 검사합니다
네 여기서 흥미로운 게 있어요 판드버그의 주석을 보면 절반은 tcache로
연결됐고 나머지 절반은 패스트빈으로 보내졌어요
이 덩어리들은 모두 같은 크기인데 어떤 통에 떨어지는지 어떻게 정할까요?
네 그런데 tcache는 통마다 덩어리를 저장할 수 있는 한도가 있어요
네 이 제한을 제어하는 변수는 'mp_count'에 있고 'tcache_count'로 표시됩니다 ?????
기본값은 7입니다 'tcache' 명령을 사용하면 0x20
tcache 카운트 필드가 한계에 도달한 걸 볼 수 있죠
네 치카빈을 채우면 이 정도 크기의 덩어리는 우리가 익숙한 패턴으로 돌아갑니다
이 경우에는 전부 0x20 크기라서 치카빈
크기가 차면 남은 덩어리를 0x20 패스트빈으로 보냅니다 ?
네 0x90 덩어리로 처리했다면 0x90 티카빈을 다 채웠을 때 남은 덩어리가
합쳐져서 무체계 빈으로 연결됐을 거예요
PDF에서 무료 플로차트를 보면 이 동작의 시각적 표현이 나오죠
네 네 타깃 tcache빈에 넣어서 정상 할당 패턴을 재개하거나
tcache 상한선인 0x410을 넘는 사이즈로 사용하면 됩니다 ,
네 흥미롭게도 tcache를 전부 우회하려면 연삭 기능은 tcache에서 분배되지 않아요
네 말록을 키우는 사람들은 '치카치 덩어리'가 더티하다고 합니다 왜 '더티'인지는
설명되지 않았지만 말이죠
맞습니다 로컬에서 운영한다면 환경 변수를 이용하여 tcache_count를 포함한 몇몇 글리브의 내부
제한에 영향을 미칠 수 있습니다 환경 변수를 이용해서요
네 호기심이죠 set user ID와 set group ID 이진수에선 무시되거든요 하지만
완성도를 위해 이 비디오 마지막에 잠깐 살펴보도록 하죠
"컨텍스트 코드"는 데모의 마지막 루프를 보여줍니다 7x20 크기의 청크를 요청합니다
네 tcache에서 할당된 할당량이 다른 통보다 우선하고 0x20 tcache빈에는
7개의 덩어리가 있어요 따라서 이 루프를 실행하는 데 0x20 tcache빈이 빈다고 해도 놀랄
일은 아니죠
16번째 라인에 중단점을 설정해 확인합니다
계속하고 'bins' 명령을 발령합니다
tcache는 비었고 아직 7개의 덩어리가 남아 있습니다
이 데모 바이너리가 마지막으로 할 일은 0x20 크기의 덩어리를 하나 더 요청하는 겁니다
네 이 부분은 물론 0x20 패스트빈에서 할당될 거예요 유일하게 사용 가능한 통이니까요 ?
네, 맞아요
'다음'을 외치며 요청하세요
네 저희가 예상하는 건 패스트빈에 남은 가로세로 6cm 크기의
조각입니다
'바구니'를 다시 발령해서 맞는지 확인해요
네 6개의 덩어리가 남아 있는 것 같습니다 하지만 모두 tcache에 연결되어 있습니다
'tcache 덤핑'의 결과입니다 이 영상의 시작에서 언급한 용어죠
원리는 이렇습니다
패스트빈에서 한 덩어리를 할당받으면 말록은 남은 덩어리를 꽉 찰 때까지 다른
치카빈에 넣습니다
스몰빈에게도 적용되는 행동입니다 네 무체중인 것도 이 역할을 합니다 할당하려고
덩어리를 고르지 않고 트카셰에 쏟아붓는 대신 딱 맞는 덩어리를 바로 쏟아붓죠 그리고
마지막으로 맞는 덩어리를 할당하거나 최근에 채운 트카셰빈에서 하나를 꺼내는 겁니다
?
네 파일에 있는 말록 파일로 과정을 알 수 있지만 지금은 패스트빈의
전송만 신경 쓸 거예요
데모 바이너리를 보면 각 티카빈의 기본 한도는 7덩어리예요 기본 프리 전에 행동이
재개되면 패스트빈에서 덩이를 버릴 수 있어요 스몰빈과 정리가 안 된 걸 마록 도중에
버릴 수 있죠
네 이제 글리벡 버전 2에 소개된 tcache 더블 프리 감경 조치입니다
29번과
우회하는 유일한 방법
GDB를 닫고 tcache_dup_2에 익숙해지도록 하죠 31진법
네 체스크섹은 최근에 우리가 태클한 tcache_dup 바이너리와 다르지 않다는 걸 밝혀냅니다 다만 글리벡 버전
2와 연결됐다는 건 예외죠 31
GDB에 바이너리를 로드하고 실행합니다
선택합니다 메뉴도 tcache_dup 바이너리와 유사합니다 이번엔 청크를 더 요청할 수 있지만요
네 규칙도 비슷합니다 tcache 크기만 있고 16바이트까지 쓸 수 있습니다
그리고 더블 프리 버그도 있습니다
그게 뭐 대수예요?
아까처럼 두 배로 떼면 안 돼요?
확실히 아니죠 글리벡이 중단했고 오류 메시지는 tcache 더블 프리로 감지됐습니다
네 좋아요 패스트빈스 더블 프리 완화법이 드디어 tcache에 적용됐나 봐요 다시
2진법으로 이 상황을 우회해서 패스트빈 둡 전술로 해결하자
큼직한 거 두 개요
순서대로 풀어줘요 A, B, A
같은 에러 메시지로 더블 프리 감형을 촉발하고 있어요
수표의 작동 원리를 알아볼 시간입니다
_int_Fly()로 전환하고 '컨텍스트 코드' 명령을 발부합니다
네 오류 메시지가 있어요 하지만 이 작은 코드 조각에선 전체 그림을 얻을 수 없습니다
네 pwndbg는 '셋 컨텍스트 소스 코드 라인'으로 소스 라인을 더 인쇄할
수 있습니다' 하지만 더 통제되고 덜 화려하게 볼 수 있는 방법은 다음과 같습니다
수표는 여기서 시작합니다
네 네 "e"
'청크의 열쇠' 영역이 뭐죠?
차를 조사해서 알아보죠
네 더블 프리 완화법으로 그 과정을 중단하기 전에 청크 A와 청크 B를 풀어 줬어요
왼쪽 B 덩어리는 0x20 티카빈 위에 있어요
B의 fd는 a를 가리키고 a의 fd는 null이에요
이 가치는 뭘까요?
맞아요 이 둘이 뒤늦게 만난다고 생각하시겠지만 둘 다 tcache 주소를 갖고 있어요
청크의 핵심 영역이죠
글리벡 2호실요 29 그 이후 tcache로 한 덩어리가 풀리면 사용자
데이터의 두 번째 사분자는 'key' 필드로 용도 변경돼 tcache 주소가 작성된 곳으로 갑니다
이 '키' 필드는 덩어리가 없다는 표시로 사용됩니다
이걸 prev_inuse 플래그로 생각하세요 아까 것이 아니라 아까 것에 적용되는 거죠
한 덩어리가 나올 때마다 키 필드를 확인합니다 네 여기 주소가 있다면 말록은 이미 풀렸다는
뜻으로 받아들이겠죠 ? 네
' 힌트'라는 말을 쓰는 이유는 키 필드가 맞는다고 해서 공짜라는 보장이 없기 때문이에요
무작위 데이터의 불운일 수도 있죠
'리스트' 명령에 대한 설명이 이와 유사합니다
흔적적 키장은 문제가 안 돼요 할당량에 제한이 있거든요
네 만약 청크의 키 필드가 tcache 주소와 일치하면 이중 자유 경감의 주요 부분이
시작돼요
네 네 빠져나간 부분이 이미 그 통에 연결됐는지 확인합니다
안 돼요
말록이 중단하면 익숙한 오류 메시지가 떠요
수표 액수가 꽤 크네요
네 똑같은 덩어리를 다른 덩어리 밑에 숨길 순 없어요 패스트빈 둡 착시처럼 말이죠 첫 번째
덩어리뿐만 아니라 모든 덩어리를 검사해야 하니까요
아, 예 그, 찬찬히 생각해 보시면 이 감형을 어떻게 우회할 수 있을지 몇 가지 아이디어가
떠오를 겁니다
예를 들어, 애프터쓰기 버그를 써서 청크의 키 필드를 손상시키면 될 겁니다
네 이 경우 버그가 없는 건 확실하지만 그래도 키 필드는 그대로예요
우리 구세주가
토사물을 던지네요 네 네 다른 통에서 이동하는 통은 해당하지 않습니다
네, 맞아요
다양한 방식으로 이용할 수 있어요
네 예를 들어 볼게요
0x20 티카빈을 채운 다음 패스트 빈 둡 기법으로 더블프리
패스트빈에 넣습니다 0x20 패스트빈을 비우고 0x20 패스트빈에서 복사한 걸 요청해요
이렇게 하면 0x20 패스트빈의 내용물이 tcache로 떨어집니다 복제된 덩어리도 포함해서요
그 청크의 tcache fd에 손을 대서 가짜 청크를 tcache에 연결할 수 있어요
하지만 그 접근법은 좀 단순해 보여서 이 2진법을 불가능하게 조정했어요
네 해 보면 할당량 하나만 더 채우면 말록 훅을 덮어쓸 수 있어요
맞아요 하지만 이 상황을 좀 더 효율적으로 피할 방법이 있어요 지금 알아보죠
GDB를 닫고 이 기술의 pwntools 템플릿을 복사하세요
편집기 안에 있는 복사본을 열어보세요
이 pwntools 스크립트는 우리가 사용한 것과 같은 도우미 기능을 갖고 있어요.
아래로 스크롤하면 유용한 코드가 이미 나와 있습니다 0x20 사이즈 7개를
요청하고 tcache에 넣어 0x20 사이즈 tcache빈을 채우고 일반 패턴으로
다시 시작합니다
20배 더 달라고 해요 다 채우기 전에 '바보'라고 써 놓을게요
'치카빈'이 꽉 찬 상태에서 이 '멍청한' 덩어리를 빼면 패스트빈으로 갈 거예요
이게 어떻게 생겼는지 GDB와 NOASLR 옵션으로 스크립트를 실행해 보죠
'vis'로 이물질을 분석합니다
8개의 청크가 있는데 7개는 패스트빈에 연결되어 있어요
네 잘 보세요 제 각본에 '뒤엉'이라고 표시된 건 키 필드가 없어요 tcache와 달리요
네 키필드는 tcache에 연결된 청크에만 추가됩니다 이중 무료 수표가 모든 청크에 적용되지만요
, 하지만요
네 '두 번 빼기' 부분을 0x20 티카빈에 넣으면 공간이 생기니까
tcache에서 두 번 빼기 승인이 나죠
네 사실 키 필드의 무작위 데이터로 메인 체크가 작동되더라도 'dup' 덩어리는 tcache에
연결되지 않았으니 여전히 체크를 통과할 겁니다 아주 안전한 접근법이죠
편집자에게 돌아가서 '얼간이'를 살펴보죠
먼저, 10x20 크기의 덩어리를 넣을 공간을 만들어야 합니다
네 네 어차피 그래야 하니까요 패스트 청크에 티캐시 덤핑을
요청하기 전에요
for 루프를 이용해 tcache에 7x20 크기의 덩어리를 요청하세요
그다음에 두 번 무첨가 벌레를 써서 다시 한번 '얼간이' 덩어리를 꺼내면 돼요
이러면 트셰이와 패스트빈에 연결될 거예요
일반적인 옵션으로 스크립트를 실행해 확인합니다
차를 부수고 조사해요
'멍청'은 확실히 인터넷과 패스트빈에 있어요
네 다음 요청은 0x20 크기의 덩어리를 패스트빈 메타데이터를
조작하는 거예요 하지만 우린 재미있는 걸 원했죠
패스트빈덥은 현장 크기를 확인해야 해요 우린 더
많은 자유를 원하죠
이제 토치 덤핑이 등장합니다
네 네 타깃 데이터와 겹치게 할 거예요 0x20 패스트빈에
집어넣는 거죠
네 그리고 0x20 덩어리를 더 요청해요 그것도 '완전' 덩어리가 서비스해 주겠죠
이번에는 패스트빈에서 받을 거예요
네 '얼음' 덩어리를 돌려주기 전에 말록은 남은 덩어리를 0x20 패스트빈에 부어 줍니다 그리고 0x20
티카체빈에 부어 주죠
네 0x20 패스트빈 포워드를 따라가면 되죠 널을 찾거나 타깃의 티캐빈이
가득 찰 때까지요
네 이 단계에서 가짜 덩어리를 0x20 패스트빈에 연결해야 하거든요 그리고 0x20
패스트빈으로 옮겨서
우리가 조심해야 할 건 가짜 청크의 포워드 포인터뿐이에요
null인 게 나아요 tcache 덤핑 프로세스가 지도에 없는 주소를 회피하는 걸 막으려면요
다행히 타깃 데이터 근처에 널 사분자가 많습니다
그럼 편집자에게 돌아가 취재를 마무리하겠습니다
다음 주문은 'x20' 크기의 조각입니다 네 네 좋아요,
그렇군요 패스트빈 메타데이터를 조작하고 있어서 헤더에 있는 덩어리를 고려해서 목표 주소에서 16을
빼야 해요
네 네 그래서 8 바이트를 더 빼서 Fake fd가 타깃 데이터와
겹치지 않도록 합니다 네, 맞습니다,
네 왜냐하면 패스트빈과 마찬가지로 tcache의 배분량은 조정 검사를 받지 않기 때문입니다
이제 패스트빈에 가짜 덩어리를 연결했으니 다시 '얼간이' 덩어리를 요청할 수 있어요
네 할당량을 정하는 동안 말록은 남은 덩어리를 0x20 패스트빈에
넣고 티카체빈에 넣습니다 이 가짜는 지금 패스트빈에 살고 있으니 저쪽으로 옮길 거예요
이제 tcache에 가짜 정보를 요청해서 타깃 데이터를 덮어쓰기만 하면 돼요
Fake 청크를 Fd가 null이 되도록 배치했다는 걸 잊지 마세요 먼저 8바이트짜리
가비지 데이터를 써서 거리를 계산해야 합니다
마지막 대사를 추가했으면 제작 조건에서 스크립트를 실행하세요
메뉴 프린트 리턴을 눌러 메뉴 프린트한 다음 옵션 3을 선택합니다 대상 데이터가 덮어썼다는
걸 보여주면 좋겠네요
글리벡 2에 도입된 tcache 더블 무첨가 조치에서 벗어났어요 29세, 임의로 글을 썼습니다
요약하자면, tcache 덤핑을 이용해서 패스트빈의 가짜 덩어리를 tcache로 옮겼어요
네 우선 0x20 패스트빈에 '차체빈'을 채워서 정당한 '차체'를 패스트빈에
넣을 거예요
네 '엉망'을 끼우고 0x20 체내에서 '엉망'을 빼고 '엉망'을
다시 넣어서 제거했어요
네 청크가 수술 대상이 될 예정이었기 때문에 패스트빈스 무료 감형은 적용되지 않았습니다
네 tcache는 더블 프리 감형이지만 '망할' 부분은 tcache와 연결되지 않아서
주요 영역이 채워지지 않았고 그래서 승인되지 않았죠
그래서 '멍청' 덩어리가 양쪽과 연결돼 있어요
네 다시 요청했어요 자체 패스트빈 fd에 덮어씌워서 타깃 데이터를 겹치는 가짜
덩어리를 패스트빈에 연결하는 거죠
네 '망할'을 또 요청했어요 이번엔 패스트빈에서 할당받아서 cache를 떨어뜨릴 수 있어요
네 티케시 덤핑 프로세스가 패스트빈에서 가짜 덩어리를 옮겨서 크기를
확인한 후 tcache로 옮겼는데 그런 수표가 없어요
네 마지막으로 드디어 ????
tcache intals에서 기억을 새로 고침하고 싶다면 HeapLAB PDF가 제공합니다
강의 자료에서 이용할 수 있는 주석이 달린 착취 스크립트도 있습니다
네 네 앞서 언급했듯이 다양한 방식으로 할
수 있습니다
예를 들어 패스트빈덥을 먼저 이용하면 말로크에게 한 번 더 전화해야 하지만 가짜
청크의 fd가 무효일 필요는 없습니다
좋아요, 잊지 마세요 스몰빈과 무체중 빈 사이에서 덩어리를 옮길 수 있어요
그리고 그 녹록은 스몰빈을 완전히 무시하고 더 많은 가능성을 열어 주죠
말록 시험대에 연녹색 연고를 추가했어요
말록의 내장이 마지막으로 안 보이는 건 글립코 2입니다 네 30 tcache빈 검사에서 할당된 혈중
혈중 혈중 농도가 0이 되지 않도록 글리벡 2를 사용했지만
31살이고,
그래도 우리 공격엔 영향이 없었어요
이 2진법에서 껍데기를 떨어뜨리는 걸로 마무리해야겠네요
네 숨겨진 문제는 없으니 비디오를 잠시 멈추고 혼자 해보시길 권해드립니다
네 다 했으면 여기로 돌아와서 같이 셸을 떨어뜨려요 말로크에 영향을 미치는 환경
변수를 간략히 설명할게요 아까 암시했듯이
큰 문제 없이 껍질을 되찾았겠죠 그래도 빨리
끝내죠
평소처럼 제가
임의로 편집해서 넣을게요 여러분도 그렇게
해도 되고 복사해도 돼요
가장 먼저 할 일은 임의로 쓰는 글의 대상을 바꾸는 거예요
네 바이너리의 주소를 무료 바늘 주소로 바꿔요 16은 빼는 거 잊지 말고요 패스트빈에 연결하고 있으니까요
tcache가 아니라요 , 좋아요
네 명령줄이 들어있는 덩어리가 필요합니다 명령어를 적당한 크기로 작성하세요
나중에 쉽게 쓸 수 있도록 레이블을 붙여야 합니다 ,
목표 데이터를 원래 덧씌웠던 선에서 글립벡 시스템 주소로 win string을
바꿔 () 함수
네 자 이제 프리 훅에 시스템 주소가 있을 거예요 이제 명령줄이 든 덩어리만 빼내면
돼요
최종 변경 사항이 있으니 생산 조건에서 착취를 실행하세요
껍데기도 하나 사요
마무리하기 전에 말로크에 영향을 미치는 환경 변수를 보여드리기로 약속했죠
그렇군요 말록의 매개 변수 중엔 환경에 따라 달라지는 변수가 있어요
이는 맬롭트를 열면 발견된다 남성 페이지에서 '환경'이란 단어를 검색한다
네 멀롭트 멀록의 매개 변수를 런타임에 제어하는 기능입니다 이 과정 후반부에 더 자세히
살펴보겠습니다
네 맨페이지를 보면 예를 들어 예를 들어 토끼의
집 개발에도 유용하겠죠 ?
네 어떻게 작동하는지 보여드리죠 물론 선택한 환경 변수를 일반적인 방법으로 설정할
수도 있어요 프로그램당 또는 세션당요
GDB 내에서 설정을 하면 효과를 결정하는데 도움이 됩니다
명심하세요 환경 변수를 통해 설정된 말록의 변수는 말록이 초기화됐을 때만 실행됩니다
또 다른 흥미로운 환경 변수는 글리브_트너블스예요 이 '참치'라는 게 글로브의 여러 변수를
커버해요 말록도 포함해서요
네 네 글리브씨에게 넘겨져 콜론으로 분리됩니다 , 글리브씨_트너블스
변수에요
네 어떤 참치가 있는지 찾는 빠른 방법은 GDB 내에서 "참치_리스트" 배열을 버리는 겁니다
????
네 네 mmap 한계점도 글리벡_트너블스로 정할 수 있는데
특이한 어묵들이 좀 있어요 , 어묵이
예를 들어 튜너블_리스트 항목 21은 'tcache_count'로 되어 있습니다 당연히 맬록의 mp_스트럭트에서
tcache_count 값을 설정해야 합니다
네 네 0으로 설정하면 tcache가 작동을 멈춥니다 "3배"
"3배"
네 네 글립비가 내용을 바꿀 수 있다는
거예요 이 작업을 가능하게 하기
위해 변수는 그 자체의 공간에 복사됩니다
이 공간은 sbrk에서 관리합니다
네 힙 매핑의 시작에 메모리를 버리면 힙 시작
전에 변수를 볼 수 있습니다 힙 시작 전에
이 값은 tcache 청크의 크기 필드입니다
네 여기 GLIBC_TUNABLES가 매핑됩니다 유효하든 아니든요 이걸 이용해 기본 힙 시작 주소에
영향을 줄 수 있습니다
네 안타깝게도 안타깝게도 사용자나 그룹 ID와 효율적인
사용자나 그룹 ID 사이에 차이가 있으면 무시됩니다 사용자 ID 바이너리
같은 거요 ,
네 게다가 참치 파일의 보안 레벨이 tcache_count의 "ERASE"라면 아동 프로세스에
패스하기엔 너무 위험하고 사용자 ID 바이너리가 환경에서 완전히 삭제될 수 있습니다
네 네 이로 인해 좌절된 착취 벡터를 발견한다면 예를 들어, 유약한 아동 프로세스를 호출하기
전에 효과적인 사용자 ID와 일치하는 사용자 ID 바이너리를 설정하는 경우 이 구현에
버그가 있다는 걸 알아두세요
글리브 같은 튜너블을 두 번 포함하면 사용자 ID 바이너리로 선택된 튜너블을
하위 프로세스에 전달하기에 충분합니다
2부가 출간될 때쯤이면 버그를 보고할 것 같아요 책임 있는 공개죠
tcache 더블 프리 완화와 우회법을 배웠습니다
마지막에 환경 변수들을 다루는 것도 재미있었어요
tcache_dup_2에서 셸을 떨어뜨리는 주석화된 취약점이 있어요 31개의 바이너리를 이용할
수 있습니다
그리고 저희가 슈랩랩랩 PDF와 말록 시험대가 실험을 도와줄 거예요
다음 영상에서는 마지막 2진법 과제에 도전합니다 이건 당연히 트캐쉬예요
트캐시에 대해 배운 것에 익숙해지면요
거기서 봐요