네 이번 시간에는 토끼의 집이라는 기술을 배워 보겠습니다 2017년, 시프트 크롭스라는
핸들로 불리는 시미즈 유타로가 개발한 기술로 ?
도쿄 서양 ctf의 일원이다 네 가짜 덩어리가 있어서 이렇게 명명했죠
'토끼처럼 뛰어다닌다'
네 토끼의 집은 원시적인 힘을 발휘하지만 물이 새지는 않습니다
확인해 보죠
토끼 디렉터리로 검색하세요
네 예상대로 토끼 집을 집중적으로 분석할 겁니다 ctf 스타일의 c# 버그도
있고 힙 버그를 이용할 겁니다
네 이 두 가지 생명체가 어떤 보호를 받았는지 짐작할 수 있다 해도 여전히 확인할 만한 연습입니다
체스크섹을 이용해 알아보죠
렐로 스택 전체와 카나리아, nx를 모두 사용하지만 포지션은 독립적이지 않습니다 글립코
버전 2를 다루고 있는 것 같군요 그것도 25달러죠, 하지만 글리벡의 집 버전은 2까지
사용할 수 있어요 네 27마리요
말록 내장이 새로 생겼어요 이 기술을 배울 건데 때가 되면 다룰
거예요
우선 목표 쌍성을 살펴보도록 하죠
복사본을 GDB에 로드해 실행하겠습니다
우리 나이에 맞춰 주라고 부추기는 건 관대해요
이제 알겠죠? 이 입력값으로 임의 숫자 없이도 메타데이터를
위조할 수 있어요
33을 입력하겠습니다
숫자가 매겨진 메뉴가 제공하는 걸 보기 전에 GDB를 ctrl+c로 시작해 'dq' 명령을 이용해
메모리를 시각화하죠 "target" 기호에서 시작해서요
네 늘 그렇듯 토끼의 집을 이용해 만들 대상은 프로그램
데이터 섹션에 있는 짧은 x줄입니다
타깃 데이터에서 조금 떨어진 지점은 관례적인 '유저' 스트럭트입니다 여기서 시작하죠
이곳은 '에이지' 밭입니다
네 이런 걸 확인하려면 1부에서 배운 GDB의 'ptype command'가 여러분의 친구란 걸 기억하세요
그래서 목표 데이터보다 높은 주소의 4분의 1을 제어할 수 있죠
네 네 , "계속"
네 옵션 1은 덩어리 9개를 요청할 수 있습니다 덩어리의 최대 크기는 제한되지 않아 할당
후 사용자 데이터에 입력할 수 있죠 ? 네
디폴트 패스트빈 범위인 0x20부터 0x80까지 4명만 들어갈 수 있어요
네 좀 억지스럽긴 하지만 전에도 말했듯이 선택지를 제한하려고 의도적으로 그런 겁니다
눈앞의 기술에 집중하려고요
옵션 2는 덩어리를 자유롭게 할 수 있고 늘 그렇듯 인덱스로
하죠, 0에서 시작해요
네 지금까지는 키나 나이 같은 입력 정보를 프로그램 데이터
섹션에 저장하는 게 이 경우 수정할 수 없었습니다
네 하지만 '래빗의 집' 프로그램은 옵션 3에서 언제든 '에이지' 영역을 변경할 수
있습니다
토끼의 집 기법에서 아주 중요한 부분인데 왜 그런지 잠시 후에 알아보죠
네 마지막으로 '포기' 옵션 외에 옵션 4는 조금 전에 조사한 타깃
데이터를 출력합니다 ???? 물론 우리 목표는 우리 데이터로 그 표적을 덮어쓰는 겁니다 토끼의 집이라는 이름으로
원시적인 단어를 임의로 작성해서요
다 끝나면 임의로 쓴 글자로 껍질을 떨어뜨려요
이제 바이너리의 원리를 알았으니 천천히 익숙해져서 버그를 찾아요
잠시 후에 봐요
지금쯤이면 벌레를 빨리 찾았을 거예요
네 오버플로를 확인하셨겠죠 하지만 덩어리에 데이터를 쓸 수 있는 건 16바이트밖에 안 됩니다 크기에
상관없이요
네 사용자 데이터는 할당 직후에 한 번만 쓸 수 있기 때문에 버그가 없습니다
이제 더블프리만 남았는데 그게 이 프로그램의 핵심인 건 이미 아시겠죠
네 두 번 연속으로 무료로 사용하려고
하면 GDB가 멈추고 스크롤하면 패스트빈의 무료 오류 메시지가 나타납니다
버그가 생겼으니 전략을 짜야죠
목표는 목표물의 데이터를 덮어쓰기입니다 주소는 0x602010
네 물론 우리가 가짜 덩어리를 만들어 도움을 줄 겁니다 'user' 스트럭트에서 우리가 통제하는 네
글자를 사용해서요
그렇군요 토끼 집의 문제점은 가짜 덩어리가 목표 데이터보다 더 높은 곳에 있다는
거예요
네 전에 포스 오브 하우스 기술에서 이 문제를 극복했어요 아주 큰 덩어리를 할당해서
가상 주소 공간에 감쌌죠
네 이 상황에도 같은 아이디어를 적용하면 어떨까요? 가짜 덩어리의 크기를 큰 값으로 설정해서
재향 군인회 공간을 둘러싸도록 할당하면 목표 데이터에 약간 못 미치게 막는 거죠
네 이 접근법의 장점은 무력재판소보다 더 좋은 점은 더 많은 정보를 누설할 필요가 없다는
거죠 가짜 덩어리와 표적 사이의 거리가 상대적이니까요
이 최종 상태를 염두에 두고 우리의 목표와 버그를 연결할 수 있는지 되짚어 보죠
가장 먼저 극복해야 할 건 엄청난 양의 살점을 할당하는 겁니다
백악관 오브 포스에서는 글립비씨 버전이 쉬웠어요 29번 창고에는 상부 크기를
확인할 게 없어요
큰 요청이 경기장 쓰레기통에서 처리되지 않는 한 부패한 최상위 청크가
사용됩니다
네 하지만 우리는 맨 위쪽에 할당하지 않고 가짜에 할당하려고
합니다
네 물론 Fake 청크를 아레나에 연결해야 하지만 어느 박스에 연결하는지도
중요합니다
큰 고객은 정리가 안 된 고객이나 적절한 고객에게만 서비스됩니다
맞아요 즉석에서 패스트빈에 넣거나 하우스 오브 로어를 스몰빈에
넣고 잘되길 바랄 순 없어요
맞아요 게다가 정리가 안 된 부분을 배분할 때는 크기를 확인해야 합니다 로어
하우스의 첫 영상에서 잠깐 다뤘던 내용이죠
네 이 수표는 가짜 물건을 함부로 쓸 수 없어요 수표보다
훨씬 커야 하거든요
하지만 라지빈의 배치는 어떤 사이즈 검사도 받지 않습니다
또한 가장 큰 라지빈은 서비스 가능 요청의 용량에 한계가 없다는 걸 기억하세요
네 가장 큰 라빈에 우리 가짜 덩어리를 연결하면 안전하게 더 큰 배당을 할
수 있어요
네 참고로 가장 큰 라지빈은 126 bin이라고도 불립니다 경기장 'bins' 배열에
있어서 붙은 이름이죠 127번 상자는 아직 사용 안 했어요
네 네 이미 다 배웠잖아요 네, 맞아요
안타깝게도 더블 프리 버그는 사용자 데이터의 양을 조절할 능력이 부족합니다 가짜 데이터의
4분의 1밖에 조절할 수 없기 때문에 이 기술을 사용하기가 어렵습니다 불가능할 수도
있죠
설령 로어 하우스를 이용해서 가짜 조각을 무정지 상태에 연결하고 126번
쓰레기통에 분류한다 해도 그 과정에서 무정지 상태가 변질되면 거기서 진전이 아주 어려워져요
네 아주 큰 덩어리를 더블프리스로 빼내고 패스트빈 둡 기법으로 했던 것처럼 메타데이터를
조작하면 좋을 거예요
하지만 일반적인 더블 무첨가 감형은 다음 무... 뭐시기 사용 전 표시를
확인하니 이건 안 될 거예요
다른 방법은 없나요?
경험상 패스트빈은 손대기에 가장 안전한 통이죠
네 가짜 덩어리를 확실히 연결하려면 4글자 하나만 변질하면 돼요 패스트빈덥을
이용하면 되죠
가짜 청크의 메타데이터는 적당한 크기 필드만 있으면 돼요
그럼... 문제는 가짜 덩어리를 패스트빈에 연결했는데 어떻게
말로크를 설득해서 가장 큰 라지빈으로 옮길까요? 안 돼요!
이건 토끼의 집이 보내는 메시지예요
이론은 이 정도면 됐고요 열려 있으면 gdb를 닫고 pwntools 템플릿 스크립트를 복사합니다
에디터에서 열게요
네 네 맬록() 옵션 1의 랩과 데이터의
덩어리를 가져갑니다 간단히 덩어리 지수를 정합니다
. amend_age() 같은 이름의 메뉴 옵션을 래핑해 'user' 스트럭트의 값을 변경할 수 있습니다
그리고 1부에 나왔던 포스 하우스 기법의 기능도 부활합니다
이걸 이용해서 가짜 청크와 표적 데이터 사이의 거리를 계산할 겁니다
스크립트 네 helper 함수의 사용과 함께요
네, 맞아요
네 0x20 사이즈로 처음 두 번 요청한 거 끝나면 다 정리해요 그걸 이용할 수 있어요
총 9개를 할당하는데 4개만 빠른 크기가 돼요
약속대로 가짜 덩어리를 패스트빈에 연결할게요 더블 프리 버그를 써서요
무료 기능을 사용하세요 도우미는 패스트 A를 두 번 무료로 해 줍니다 그 사이에 패스트 B를 무료로 해 패스트빈을
우회합니다 더블 프리 감형
여러분 패스트빈 둡 기술을 다시 배우고 싶다면 해리랩 PDF에서 알려드립니다 아니면 1부에서
패스트빈 둡에 대해 다시 배우셔도 됩니다
이미 알고 계시면 좋겠네요 다음 단계는 빠른_A 덩어리를 한 번 더 할당하는 겁니다 0x20 크기의
덩어리를 다시 요청해서요
이걸... 이걸 이용해 빠른 덩어리를 덮어쓸 거예요 Fake 덩어리를 가리키도록요 "user"
스트럭트의 주소에서 준비하겠습니다
네 이렇게 하면 '유저'의 '에이지' 영역이 마음대로 바뀔 수 있어요 가짜
청크의 영역이 되죠
네 모든 게 계획대로 되는지 확인하죠 GDB와 NOASLR 옵션으로 스크립트를 실행해서요
GDB를 ctrl+c로 추가합니다. 그런 다음 'vis' 커맨드로 기본 힙을 검사합니다.
출력합니다 출력된 걸 보면 패스트_A와 패스트_B 덩어리가 보이는데 둘 다 0x20 패스트빈에 연결돼
있어요
패스트빈 네 패스트_B는
0x20 패스트빈의 끝에 있습니다 패스트_B는 패스트빈의 끝에 있습니다 fd는
패스트_A를 가리키고 패스트_A의 fd는 가짜 청크를 가리켜 주소는 0x602040이야
기억하세요 이 값은 처음에 설정한 "age" 변수입니다 런타임 동안 수정할 수 있죠 , 이건 시작에 설정된 "age"입니다
네 네 0x20 패스트빈의 크기가 알맞죠 33이 16진법의
0x21이니까요 "36진법"
네 계속해야죠 alt++로 프로그램 창으로 바꾸고 return을 누릅니다 여기까지 오기
위해 4개의 빠른 청크 중 3개를 이미 사용했다는 걸 상기시켜요
네 그래서 패스트빈덥을 활용할 때 일반적인 방법은 안 통해요 가짜 바늘을 요청해서 말록
갈고리를 겹치게 한다든지 그런 거요
맞아요 대신 원래 계획대로 해야 해요 보훈 병원을 감싸기에 우리
가짜 살덩어리가 크다고 믿게 해서 임의 기억을 공격해야죠
네 Fake 청크의 크기를 조정합니다 "age" 변수를 이용해서요 그냥 큰 값으로 설정하고 요청하면
안 되나요?
네 이 방법은 가짜 덩어리가 패스트빈 크기 검사에 걸릴 뿐 아니라
말록이 패스트빈을 뒤지지도 않을 겁니다
아까 말했듯이 이걸 하려면 가짜 덩어리를 라빈으로 옮겨야 해요
그래 네 니다니다, 보세요
먼저 패스트빈에서 무체중으로 가짜 덩어리를 옮겨야 해요
어떻게 할 건데요?
정답은 말로칸이라는 기능입니다 경기장의 패스트빈에 있는 모든 덩어리를 무정제
상태로 흘려보내서 덩어리를 하나로 고정하죠 가능하다면요
네 메모리 요청이 서비스되지 않으면 패스트 덩어리가 고물 분열을 일으키기 때문입니다
네 네 말로크_콘솔리데이트를 통해서요 요청이 받아들여질
만큼 큰 덩어리가 나올 겁니다
네 패스트빈의 목적에 어긋나기 때문에 특정 기억 압력 조건에서만 발생합니다
네 이제 연락 못 해요 직접은 안 돼요 말록의 핵심 기능에서 전화가
오는데 말록 내 두 곳과 무료 내 한 곳도 포함돼요
다행히도 패스트빈 경화 현상은 간접적으로 간단합니다
네 히랩랩 PDF 파일을 참조하면 말록 흐름도 상 두 지점이 나오는데 말록 흐름도라는
지표예요
이게 제일 접근하기 쉬워요
큰 덩어리를 요청하면 돼요 400배 이상으로요
그렇게 해보죠
편집자 앞으로 돌아가세요
'데이터' 논쟁에 쓰레기를 보낼 경우 0x400 이상 요청하세요
스크립트를 다시 실행하세요 GDB와 NOASLR 옵션으로요
멈춰야 해요
네 반사 신경이 좋다면 세그폴트 에러 메시지가 빠르게 지나가는 걸 봤을 거예요 아니라면 확인을 위해
위로 올려 주세요
하지만 말록합성을 촉발할 수 있었어요 역추적 검사에서 증거로 드러났죠
뭐가 잘못됐나요? 소스 코드 패널에 따르면 세그폴트가 언링크에서 발생했습니다
'nextchunk' 변수를 프린트해서 어떤 덩어리가 링크를 풀었는지 확인할 수 있어요
네 네 가짜 메모리 직후에 메모리 지역 링크를 풀려고
해요 , 말록이
네 네 가짜 덩어리 다음에 또 다른 덩어리가 '넥스트충크'가
통합된 후보라고 판단했어요 네, 맞아요
여러분 말록이 최종 강의에서 최종 후보를 어떻게 정하는지 알죠
1부
다시 정리해 보면 멀록은 가짜 조각의 크기를 계산하고 메모리를 남겨서 다음
조각을 찾습니다
그리고 이 덩어리의 크기 값을 보고 그 양을 가지고 스크롤을 합니다. 그리고 prev_inuse
플래그를 확인합니다. 좋아요, 세 번째 덩어리가 사용 전 깃발이 선다면
가짜 덩어리 뒤에 있는 것도 합체된 후보가 될 거예요 그럼 말록이 가짜 덩어리를 앞으로
보내겠죠 거시기
지금 그런 상황이에요
네 멀록이 가짜 청크 사이즈 필드 0x20을 확인합니다 그리고 메모리를 앞으로 스크롤하죠
그 주소에서 마주치는 영역은 0이에요
네 이 과정에서 멀록은 크기 보전성을 확인하지 않고 0바이트씩 앞으로 스크롤을
내려서 같은 자리에 놓습니다
네 말록이 그 위치에서 사용 전 깃발을 확인해요 그건 확실해요 가짜 덩어리 다음에
나온 덩어리가 통합된 대상이라는 뜻이죠
네 세그폴트요 말로크가 앞뒤로 있는 네 단어를 제거하려고 할 때 전후방의 위치를
가리키는데 이 존재하지 않는 덩어리에 속해요
자 우리가 정상 참작을 촉발하진 않지만 우리 선행을 방해하는 겁니다 어떻게
하면 이걸 피할 수 있죠?
네 우리는 이미 뒤로 가는 통합을 막고 있습니다 fake 청크 사이즈 필드에 prev_inuse 비트가 설정돼
있기 때문이죠 하지만 우리의 영향력은 거기서 끝납니다
네 이 지역의 메모리를 더 통제할 수 있다면 울타리 조각을 제공할 수 있지만 한 자릿수만
통제할 수 있어요 밭 크기를 조절하려면 그 자릿수가 필요하죠
네 생각해 보죠 그 자체로 앞뒤로 거대해지는 걸 막을 수 있는 게 있을까요?
정답은 예스입니다. GDB를 닫고 편집자에게 돌아가세요.
자 이 문제를 직접 풀고 싶다면 지금 영상을 멈춰 답을 알아낸 후에 다시
시작해
원조 래빗 하우스 기법은 통합 문제를 극복하려면 2사분기 이상을 통제해야 했습니다
가짜 덩어리를 가능한 한 가장 큰 값으로 설정합니다
15f 다음에 1이죠 그리고 그 앞에 울타리 덩어리를 놓습니다
이로 인해 가짜 고물이 스스로 전면 보호대를 갖추게 됐죠 네 말록은 자기 영역 크기를 보고 그 크기를
앞으로 밀어서 다음 덩어리를 찾아요 그렇게 재향 군인회 공간을 감싸다가
울타리 기둥에서 멈추죠 가짜 덩어리 바로 앞에서요 안 돼요
네 네 오렌지 하우스 1부에선 말록이 이걸
사용했습니다
이런 접근법은 근처 사분어초 두 개를 통제한다면 가능하지만 슬프게도 한 개만 통제합니다
네 저희가 사용할 해결책은 이 가짜 덩어리를 포워드 통합 가드로 만드는 겁니다
다른 크기를 사용해서요 그 값은 1입니다
스크립트의 "age" 변수를 1로 설정하고
일반적인 옵션으로 다시 실행합니다
하지만 이번엔 세그폴트가 아니라 중단으로 멈췄습니다
네 믿거나 말거나 이건 진전이에요 곧 우리가 촉발하는 경감에 대처할 거예요 ,
가짜 청크가 있는 '사용자' 스트럭트에 'dq' 메모리를 버려야 해요
보세요 가짜 크기 1입니다 이제 앞뒤 방향이 혼란스러워 보입니다 혼란스럽지
않다는 명령이 확인시켜 주죠
네 즉, 0x20 패스트빈에 있는 가짜 덩어리를 정돈되지 않은 통으로 옮겼습니다
라지빈에 한 발 더 가까워졌죠
네 네 앞으로 통합되는 것도 막아줬거든요 그래서 앞으로
통합되는 것도 막았죠
네 말로크가 크기를 확인했는데 0이었어요 플래그는 덩어리 크기로 안 돼요 메모리를 앞쪽으로
이동해서 0바이트씩 이동했죠 ?
가짜 덩어리가 이제 넥스트충크가 됐어요
네 말록이 다음 파편의 크기를 재서 0바이트 크기로 다시 스크롤을 만듭니다
가짜 덩어리가 다음 덩어리가 됐어요
여기... 이 덩어리에 사전 사용 비트가 있어서 말록의 관점에서 이 가짜 덩어리 뒤에 있는 덩어리는
공짜가 아니라는 뜻이죠 그래서 통합되지 않은 거예요 안 돼요
네 그 결과 가짜 지방이 무체중 혈관에 연결돼서 세그폴트를 피하게
되죠
네 디폴트 힙에 할당된 빠른 덩어리는 여기 없어요 상단 덩어리와 통합됐기
때문이죠
기억하십시오, 모래 뭉치는 보통 덩어리처럼 무료 패스트 덩어리를 처리합니다
잘 들어 이게 좀 혼란스럽다면 바로잡을 좋은 방법이 있어 멀록_언설리드에서
중단점을 설정해 네 폰툴 대본에서 스크립트 시작 부분에 있는 "g" 변수를 수정해서 이렇게 할 수 있어요
그럼 당신이 궁금해하는 변수를 프린트하면서 말록을 추적할 수 있어요
상황에 익숙해지면 다음 문제를 해결하죠
좋아 지금까지 지금까지 '감시되지 않은' 버그로
점프했습니다 "감시되지 않은 버그"
네 가짜 덩어리를 라지빈에 넣기 전에 계획을 취소해야 합니다 일단 중단해야죠
_int_malloc으로 전환 () 프레임과 '컨텍스트 코드' 명령을 발부하세요
네 이건 정신 상태 검사예요 전에도 본 적 있죠 잠깐이지만요 ? 정돈되지 않은 청크가 할당되거나
분류되어 적절한 크기 값을 갖는지 확인하기 위해 존재합니다
센서블은 여기서 울타리보다 작지 않고 Arena 시스템_mem 값보다 크지 않다고 정의됩니다 ??????
네 1부 패스트빈 둡 도전에서 시스템_mem에 관해 얘기한 적 있죠 이 아레나에서 핵에서 확인한
메모리의 총량을 기록한 거죠
이 가짜 덩어리는 네 처음부터요
좋아요,
네 네 말록이 흐름을 확인한 직후 흐름이 없는 통을
뒤지면 가짜 말록이 발견되는데 크기는
안 맞아요 정신 건강 확인
안 돼 문제가 생겼어요 말로크_콘돌리드에 연락해야 해요 가짜 덩어리를 무체중 혈관에 넣고 세그놀팅을
피해야 해요 가짜 덩어리를 부적격 크기로 만들어야 해요
다행히 이 딜레마에 해결책이 있습니다
네 한 가지 방법은 가짜 덩어리가 도착하기 전에 한 덩어리를 무정지 상태로 보내는 겁니다
네 이렇게 하면 우리의 큰 요청이 여전히 멀록_콘서드를 작동시킬 겁니다 하지만 쓰레기통에 있는 큰 덩어리를
할당받으면 수색이 가짜 덩어리에 도달하기 전에 할당받을 수 있죠
두 번째 방법은 더 효율적이니 그걸 이용할 겁니다
좋아요, 네 , 보세요
네 정상 덩어리를 분리할 때 덩어리 크기가 패스트빈 통합 한계점을 넘으면
그렇게 불릴 수 있습니다
네 우리가 말록 통합을 작동시키면 말록 대신 이 방법으로 수색을
안 해도 되고 가짜도 안전히 보관될 겁니다
패스트빈 통합 한계점보다 큰 덩어리를 사면 돼요
네 패스트빈 통합 한계점은 변함이 없습니다 여러 디스커로들이 글리벡 쌍성을
다른 값으로 컴파일하는데 기본값은 65536 즉, 0x10000으로 설정됩니다
?
네 이 정도 크기의 토끼를 할당하거나 풀어 주는 건 토끼의 영역에 문제가 되지 않습니다 하지만
더 효율적인 방법이 있죠
네 분리된 덩어리의 크기를 보면 뭉친 후에 말록_합성이 되는지 알 수 있습니다
네 작은 덩어리를 풀어 줬다가 나중에 큰 덩어리와 통합되면 우리가 원하는 행동을
유발할 수 있어요 윗부분과 합병할
때도 이 방법이 적용됩니다
편집자 앞으로 돌아가세요
큰 덩어리를 훨씬 작은 덩어리로 바꿀 거예요
그럼 풀어줘야죠
네 요청은 더 이상 말로크_콘돌리드를 작동시키지 않습니다 대신 이 덩어리가 정상적으로
맨 위 덩어리와 통합될 겁니다 그 후 총 크기를 패스트빈 통합 한계점과 비교할 거고요
네 위쪽이 문지방보다 훨씬 크니까 경보기가 작동할 거야 하지만 그 후의 혼란스러운
수색 없이 가짜 덩어리를 혼란스럽게 할 거야 ? 네
수정을 하고 나면 일반적인 옵션으로 스크립트를 실행합니다
다행히도 GDB는 멈추지 않고 있습니다 ctrl+c로 브레이크 메인 아레나의 무체계 빈을
검사합니다
가짜 조각이에요 '유저' 스트럭트에서 메모리를 쏟아서 확인했죠
네 이 수거대는 꽤 안정적인 상태예요 우리가 장난쳤지만요 'vis'는 디폴트 힙에서
요청했던 모든 덩어리가 맨 위에 통합된 것을 보여줍니다
네 이제 남은 건 가짜 덩어리인데 사실상 이 덩어리는 정서가 혼란스러운 상태와
연결돼 있어요
아직 할 일이 남았어요 이제 '토끼의 집'을 분류해서 '토끼의 집'이란 말을 써야
해요 우리 가짜 덩어리를 라지빈에 넣어야죠 아무 라지빈이 아니라 가장 큰 라지빈, 126빈이죠
기억하십시오. 명심하세요. 이렇게 하는 이유는 bin 126만 제한 할당되지 않았기 때문에
나중에 할 중요한 요청을 서비스할 수 있기 때문입니다. 재향 군인회 공간을 감싸고 있는 거죠
이건 간단할 거예요
프로그램 메뉴에 있는 amend_age 옵션을 이용해 가짜 청크 크기를 0x80000
이상 bin 126에 맞는 최소 크기로 바꾸면 돼요
네 그다음에는 더 큰 덩어리를 요청할 거예요 그러면 가짜 덩어리가
가장 큰 라지빈으로 분류되죠 ? 네 네 더 작은 덩어리를 요청해도 똑같은 효과가 나지만
가짜 덩어리가 남아서 혼란스러운 곳에 버려질 거예요
더 작은 덩어리를 혼란스러운 곳에 숨겨두면 막을 수 있어요 가짜 덩어리를 정리한 후에
할당받을 거예요 하지만
말록을 찾는 건 너무 위험해서 더 효율적인 방법을 택하기로 했다
편집자 앞으로 돌아가겠습니다
수정신청을 추가할 겁니다 () 방금 제가 직접 걸었어요 네 가짜 청크를 최대치로 맞출 수 없다는
걸 기억하세요 정서불안
상태의 청크 크기를 확인한 후 라지빈으로 분류해야 합니다
네 그다음 말록에 전화해서 최신 가짜 청크 크기보다 조금 큰 덩어리를
요청합니다
그 두 줄이면 가짜 조각을 큰 라빈에 넣기에 충분할 거예요 일반적인 옵션으로 스크립트를
실행하면 되는지 보죠
불행히도 GDB는 다시 한번 멈춥니다 안 돼요 중단 명령으로 취약점 경감 조치가 유도되고
있어요 역추적 패널에서요
alt+의 프로그램 창으로 바꾸면 다소 특징 없는 오류 메시지가 나옵니다
말록 에러 메시지가 무슨 뜻인지 잊으면 '핸랩랩 PDF에 있는 감형 에러 메시지'를 확인하세요
오류예요 토끼의 집에서 이런 오류는 많이 봤어요 정신 분열 상태 점검기
때문이에요
네 네 실행할 프레임으로 바꾸고 _int_malloc() '컨텍스트
코드' 명령을 발급하면요
아… 피해자 덩어리가 가짜 덩어리임을 확인한 후 이 Arena
system_mem 필드의 값을 출력하고 비교 대상
피해자의 크기를 입력하면 됩니다 아니요, 아니요
네 잘 모르겠지만 가짜 덩어리는 메인 아레나에서 확인한
전체 메모리보다 훨씬 커요 말록의 입장에선 그럴 리 없으니 작전을 중단해야죠
네 가짜 덩어리를 더 작게 만들 순 없어요 안 그러면 126번 상자에
분류 못 해요
방정식의 한쪽을 수정할 수 없다면 다른 쪽은 가능할까요?
네 system_mem이 아레나에서 빌린 전체 메모리를 의미한다면 더 많은 메모리를 요청해서 우리가 원하는
총액이 나올 때까지 값을 높일 수 있지 않나요?
한번 해보죠, GDB를 닫고 에디터로 돌아가죠
큰 덩어리를 요청합니다 네 "0x80000
혹은 그 이상으로요
디폴트 힙 시작 사이즈는 0x21000입니다
둥근 숫자로 유지하면 0x60000 덩어리는 system_mem을 0x81000으로 증가시킬 수
있습니다
네 이 배정은 대본 초반에 할 거니까 작업에 지장은 없을 거예요
추가가 완료되면 일반적인 옵션으로 스크립트를 실행합니다
아직도 착취 완화에 집착하는 것 같은데 무슨 일이죠?
메인 아레나 시스템_mem 값을 확인해서 우리 아이디어가 통했는지 확인해 보죠
변한 게 없어요
'스텝' 명령을 발령하면 0x60000짜리 덩어리가 보여야 하는데 안 보여요
mmap 한계점이라는 것 때문에 이상한 일이 벌어지고 있어요
네 말로크에게 큰 요청이 들어오면 프로그램이 이 크기의 덩어리를
자주 할당하지 않을 거라고 생각하죠
네 그래서 이 커다란 덩어리가 작은 덩어리 사이에 끼어서 회수할 수 없는 상황을 방지하기
위해 말로크는 mmap를 사용합니다 무더기에 영향을 주지 않고 직접 요청하는 거죠
그 후 어느 지역에도 없는 곳에 홀로 존재하게 됩니다 프로그램이 끝나면
시스템으로 즉시 복구할 수 있죠
네 네 0x6000000 덩어리를 이렇게 할당했는지 확인할 수 있습니다 () 함수의 프레임과 Pwndbg의
'vmmap' 명령을 이용해 우리가 요청한 첫 번째 덩어리의 매핑을 찾아서요
네 디폴트 힙 매핑과 함께 보면 이 덩어리는
다른 덩어리들이 할당된 힙에 자리잡지 않은 것이 보입니다
다른 얘기지만 이 큰 덩어리가 매핑에 포함되지 않았다는 걸 아신다면 예를 들어
pwndbg의 'incfo' 커맨드를 써서죠 걱정 마세요 커널이 mmapped 지역의
가상 주소에서 최종 결정을 내립니다 이 경우엔 기존 매핑에 큰 덩어리를 추가했어요 프로세스
초기화 동안 동적 로더가 만든 거죠
진짜 미스터리를 알고 싶다면 싱글 스레드 프로세스인 두 번째 아레나를 갑자기 갖게 된 이유를 😋알아보세요
힌트를 드릴게요 여러 가지 사건 중에 나온 거예요 libgcc를 재향
군인회 공간에 들여 역추적하려고요
중요한 건 아니지만 배울 게 있을 거예요
다시 본론으로 돌아가죠 네 네 안
돼요
네 이 덩어리의 유일한 특징은 깃발입니다 prev_inuse 비트 대신 set_MAPPED
플래그가 있죠 ?
이렇게 이렇게 해야 이 덩어리의 출처를 알고 매핑을 풀 수 있습니다 경기장으로 돌려보내는
대신에요
네 왜 덩어리가 6천 개가 아니라 6천 1000이 큰지 궁금하실 텐데요 mmap
크기가 세분성이 페이지 수준이기 때문입니다
0x60000 사이즈 덩어리는 사용하지 않는 prev_size 필드를 수용하려면 0x60000 바이트보다
한 사변수가 더 필요합니다 그 결과 추가 페이지가 매핑되죠
네 이 덩어리가 여기 온 이유는 말록이 기준치를 통과했기 때문입니다 무더기로 사는
것보다 mmap를 하는 게 더 효율적이라고 생각하죠
mmap 문지방이라고 하는 문지방을 말씀드렸죠
네 네 '말록 매개 변수'의 줄임말이죠 '말록 매개
변수'
네 스트럭트의 "sbrk_base" 필드를 알아보실 수 있을 겁니다 디폴트 힙의 시작을
빠르게 하기 위해 몇 번 사용했습니다
네 pwndbg는 명령어 'mp_'를 이용해서 빠르게 프린트할 수 있습니다 저는 GDB의 'print'
커맨드를 더 선호합니다 16진수에서 출력할 수 있기 때문입니다
좋아요, 이제 지금 이 디스트로: 0x20000은 128
곱하기 1024로 정의됩니다
네 배관공이 이걸 손봐서 말로프트라는 기능을 통해 직접 조작할 수 있는데 안타깝게도
이 시나리오에선 불가능합니다
네 문제는 mmap 임계값이 이 값에 머물러 있는 한 system_mem 값을 올리기 위해 큰 덩어리를
디폴트 힙에 할당할 수 없다는 겁니다
네 물론 더 작은 덩어리를 할당해도 되지만 이 이진법이 총 할당량에 한계가 있어서
더 효율적으로 해야 해요
네 예전에는 mmap 임계값이 고정값이었는데 지금은 청크 크기에 따라 달라져요 a 프로그램이
사용되고 있죠 ?
네 예를 들어 mmap 한계점을 넘는 덩어리를 남용하는 프로그램이
있다면 mmap로 할당하면 더 느려질 겁니다
그리고 이 덩어리가 풀려나기 때문에 기억을 묶을 위험이 줄어들죠
멀록이 능률 유지를 위해 mmap 한계점을 조정할 수 있어요
무료() 함수 내에서 완료되었습니다 여기에
해당하는 코드가 있습니다
네 'ISMAPPED 깃발만 확인하면 됩니다' 다음 IF 문장의 중요한
줄이에요
그럼... 풀린 땅덩어리가 현재 mmap 한계점을 넘으면 그 mmap 한계점을
그 가치로 올려야죠
네 이 기회를 이용해서 6천 mmap 임계치를 높일 수 있어요
다시 요청하면 mmap 대신 월등히 배정해야 해요
네 그리고 메인 아레나 시스템_mem 값을 올려 가짜 몸뚱이가 정신 분열 검사를
통과하게 하죠 ??
그리고 이 계획을 실행할 에디터로 돌아갑니다.
시작! 대본이 시작되면 두 번째로 6천 x만 한 덩어리를 요청해서 그 사이에서 첫 번째 덩어리를
풀어주는 거예요
여러분 네 방금 보신 대로 ()
네 이걸 풀면 매핑이 풀리겠지만 그러면서 mmap 한계점을 조정해서 앞으로 이런
크기를 감당할 수 있게 할 겁니다
다음... 두 번째 0x60000 요청은 mmmap 한도 이하이며 다른 것과 마찬가지로 폐기물에서 할당됩니다
네 이 요청을 수행하려면 말록이 핵심에서 메모리를 더 요청해 윗부분을 늘려야 합니다
네 그리고 그 대가로 지금까지의 목표였던 메인 아레나 시스템_mem 값을 높일 겁니다
일반적인 옵션으로 스크립트를 실행하면 되는지 보죠
지금까진 좋아요
이 정도로는 안 끝나요 가짜는 정신감정검을 통과했다는 뜻이죠
ctrl+c로 브레이크하고 "mp_" 스트럭트부터 확인합니다
mmap 한계치가 0x20000이었는데 mmapped 청크 크기로 0x61000으로 바뀌었어요
네 네 메인 아레나 시스템_mem 값도 올랐다는
뜻이에요 이렇게 확인할 수 있죠 , 보세요
메인 아레나 시스템_mem 값이 0x81000에서 0x21000으로 올랐습니다
네 가짜 덩어리는 기억하시겠지만 현재 0x80000 사이즈로
나옵니다 큰 통에 분류하면서 혼란스러운 빈 크기 검사를 통과했습니다
라지빈 명령으로 확인해 보죠
드디어 126번 쓰레기통에 연결됐어요
'dq'나 '말록_청크'로 확인할 수 있어요
보세요, 앞으로 뒤로 front_nextsize back_nextsize 포인터입니다
fake 청크는 이 bin에 연결되어 있어요 경기장 안정성을 유지하는 데 이점이 있죠
네 네 ????
네 큰 라빈과 연결돼 있어요 할당된 공간은
제한이 없고 크기 확인도 안 해요
이제 GDB를 닫고 편집자로 돌아가서 취약점의 최종 변경을 해 보죠
스크립트 끝으로 가서 amend_age에 전화를 추가하세요() 도우미 함수
기억하세요 프로그램 데이터 섹션의 'user' 영역이 가짜 청크 크기
영역 역할을 한다는 걸요 최대한 큰 덩어리로 바꿀 거예요
네 이제 원시적인 형태의 집이 생겼고 나머지 공격도 그 기술과 아주 유사합니다
네 먼저 가짜 덩어리와 표적 데이터 사이의 거리를 계산합니다 거기에 델타() 도우미 기능을
사용할 수 있죠 포스 해킹 스크립트에서 했던 것과 똑같이 작동합니다 ???
그런 다음 가짜 덩어리에서 공간을 할당해 그 과정에서 다시 채우죠
나머지는 목표 데이터를 중첩해야 하는데 나머지를 할당해서 덮어쓸 수 있어요
다음과 같습니다 마지막 대사를 추가하면 GDB와 NOASLR 옵션 없이 생산 조건에서
착취를 실행하세요
네 메뉴를 보여주려면 eturn을 누르고 옵션 4를 선택해 타겟을 프린트합니다 하우스
오브 래빗 기법을 이용해 임의로 작성했다는 걸 보여주죠 ????
네 요약하자면 이 바이너리에 더블 프리 버그를 넣어서 패스트빈에 가짜 덩어리를 연결했어요 다른 버그를
써도 같은 결과를 얻을 수 있지만 더블 프리 버그가 전부였어요 ,
그리고 말록합성을 촉발해서 패스트빈에서 무체중으로 가짜 덩어리를
옮깁니다
네 이렇게 하면 위쪽을 둘러싼 보통 덩어리를 분리할 수 있어요 더 효율적으로
하려면 그냥 두 번째 덩어리를 분리하면 되죠
기억상실증 기억을 되살리고 싶다면 PDF 파일에서 '말록
기능' 부분을 확인하거나 말록 플로차트를 검색하세요
멀록 멀록과 통합하기 위해 가짜 덩어리를 주변 공간과 통합하지 않고
사용 전 깃발을 설정해 뒤로 통합을 막습니다 크기는 0으로 설정합니다
바로 이겁니다 이 가짜 덩어리가 또 다른 덩어리가 되어 앞으로의 통합을
막아줄 겁니다 네 가짜 덩어리를 무체중 빈에 안전하게
연결한 후 크기를 0x80000으로 바꿨습니다 가장 큰 라지빈이나 bin 126에 적합한 작은
사이즈죠
네 분류하기 전에 정돈이 안 된 상태인지 정신 건강 검사를 통과해야 했어요
네 그 과정에서 Arena의 system_mem 값을 페이크 청크 크기 이상으로 증가시켜야 했습니다 혹은 그 이상으로요
네 0x60000개의 덩어리를 폐기장에 배치함으로써 system_mem 합계가
0x21000에서 0x81000으로...
네 그리고 그 결과 그 대가로 두 번째 0x6천
개씩을 할당받을 수 있도록요 mmap 대신에요
네 네 크기 제한이 없는 거죠 최대한 큰 가치로 크기를
바꿨어요 안 돼요!
네 마지막으로 정신 건강 검진비가 부족해서 가짜 데이터에서 할당을
받았어요 목표 데이터와의 간극을 메우려고요
네 네 목표물과 정확히 겹쳐 우리가 덧씌울 수 있어요
네, 맞아요
그건 토끼집이에요 우리가 배운 건 짧지만 이 기술에는 움직이는
부분이 많고 기억해야 할 말똥가리 내장도 많습니다
그러니 이 영상을 다시 보고 명확히 하고 싶다면 GDB에서 재생하세요
강의실에서 주석이 있는 솔루션 스크립트를 다운로드할 수 있습니다 하이랩 PDF는
우리가 배운 말록 정보와 토끼의 집 기법의 설명을 함께 제공하죠
새로운 기술로 껍질을 벗기지 않으면 해커가 아니죠 이 일에 필요한 지식은 이미
다 갖고 있잖아요
문제가 하나 있지만 해결책이 있을 거라 믿어요
지금 비디오 멈추고 한번 보세요
조개껍데기 받았어요? 안 돼도 괜찮아요 같이 해결해요
기존 취약점을 복사해서 그대로 두겠다면 내 걸 수정할게요
네 말록을 노릴 거예요 바늘을 임의로 쓸 건데 정확히는 프리 훅이죠 공격자
조종 데이터를 쓸 수 있으니까요
네 이걸 하려면 '거리'를 바꿔야 해요 가짜 청크와 프리 훅 직전의
거리를요 ? 네
네 그럼 남은 가짜 덩어리는 할당 후의 무료 훅에 겹치게 되죠
나머지를 할당할 때 가비지 1사분자를 써서 사용자 데이터의 시작과 후크
사이의 간격을 메워야 합니다 16바이트가 연결되어 있지 않으니까요 맞아요,
그다음 글리벡의 시스템 주소를 적습니다
모든 게 제대로인지 확인합시다 GDB와 NOASLR 옵션으로 취약 스크립트를 실행해서요
이상하게도 GDB는 멈춰요 _int_malloc으로 전환 () '컨텍스트 코드' 명령을 발동해 문제를 파악합니다
또 정신이 혼미한 상태의 검사를 실패했네요
이유를 알아내기가 좀 힘들 수 있어요
하지만 아직 모르신다면 시간을 두고 알아보세요
무슨 일인지 알거나 더 할 말이 없다면 계속하죠
이런 크기가 맞지 않는 건 가짜예요 가짜 바늘 바로 앞에
남은 부분을 걸어야 하죠 네 '피해자' 변수를 전달하면 처리 중인 청크의 주소를
알 수 있어요 pnbg의 '말록_청크' 명령으로요 ?
보세요 보시다시피 이 덩어리의 크기는 인공적으로 부풀린 시스템_mem보다
훨씬 커요
네 네 이전 공격에서 이 조치가 일어나지 않은 이유는 원래 가짜 청크의 공간을 너무 많이
할당해서 나머지 데이터와 타깃 데이터 사이의 간극을 메우려다 보니 나머지 사이즈가
유효 범위로 돌아온 겁니다
네 이번 경우에는 훨씬 작은 틈을 메우기 위해 거대한 가짜 덩어리의 아주 작은 부분만 요청할 거예요
재향 군인회 공간을 감싸지 않도록요
나머지는 Arena의 system_mem 값보다 훨씬 큽니다
이 문제의 해결책은 간단합니다 fake 덩어리의 크기를 조정합니다 가능한
한 큰 값으로 설정하는 대신 훨씬 작게 하는 거죠
네 가짜 덩어리의 정확한 크기를 아니까 정확한 크기를 만들어야죠 정확해야 해요
'거리' 변수를 계산한 선을 마지막 수정된 나이 전에 어딘가로 옮깁니다
네 지금 쓰는 대형 사이즈 대신 가짜를 '거리'로 바꾸고 후크랑
겹치는 최종 할당을 포함해요
네 네 하지만 꼭 그럴 필요는 없어요
,
네 malloc가 prev_inuse 플래그를 적절한 곳에 설정합니다 덩어리 alignment는 무료일 때만
확인되죠 () 따라서
잠재적으로 다양한 범위의 값을 사용할 수 있습니다
그 변화를 이루면 일반적인 옵션으로 착취를 진행하세요
이번엔 멈추지 않을 테니 좋은 소식이죠 좋아요, ctrl+c로 브레이크하고 pwndbg의
'u' 명령을 이용해 후크가 가리키는 주소로 지시 사항을 보냅니다 ???
무료 후크를 덮어씌우는 데 성공했어요 글리벡 시스템 주소로요 이제 한 단계만 남고 명령줄을
포함한 덩어리를 풀었습니다
계속 gdb로 가서 프로그램 창으로 잠시 옮기면 메뉴에 할당량이 없다는 걸 알 수 있죠 안 그러면
기존의 덩어리에 명령 문자열을 써야 합니다 셸을 원하면 사용을 중지합니다
편집기로 돌아가죠 덩어리를 골라 명령 문자열을 씁니다 이걸 선택해
문자열을 쓰죠
"빈/시" 삭제하는 걸 잊지 마세요
이름을 지어줘요 인덱스를 기억 안 해도 되게 말이에요
취약점 스크립트가 마지막으로 하는 일은 같은 부분을 무료로 제공하는 것입니다
준비되면 생산 조건에서 착취를 실행해요 그럼 껍데기가 준비될 거예요
토끼의 집 기법으로 껍질을 떨어뜨리셨네요
네 임의로 쓰는 것과 비교해서 넘어야 할 유일한 장애물은 가짜 덩어리를
미세 조정하는 거였어요 그래야 마지막 단계에서 정신 분열증을 예방할 수
있죠
네 토끼의 집은 글립코 이후 버전과 비교하면 도움이
될 수 있어요 27점입니다, 물론 prev_size check는 2번에 있습니다. 26은 메모리 컨트롤을 우회하려면
4분의 1이 필요하고, 2는∙∙∙ 27은 네 () 기능으로 취약점을
약간 변경했습니다
토끼의 집을 이용해 글리벡 2를 어떻게 바꿔야 할지
알고 싶다면요 27, 토끼 2호 집으로 탐색 27 디렉터리에는 바이너리와 pwntools
템플릿 스크립트가 있습니다 네 비디오 형식으로 세부 사항은 다루지 않겠지만 같은 디렉토리에
솔루션 스크립트를 제공했어요, 막힐 때를 대비해서요
네 말씀드렸다시피 힙랩 PDF는 잊힌 기술과 말록의 내부를 기억하게
해 주는 프로그램입니다 불분명한 부분이 있다면 영상 일부를 다시 보세요 멀록의 시험용 침대가
유용할 거예요 글립벡의 여러 버전으로 공격 테스트를 하고 싶다면요
네, 맞아요. 이 바이너리에 대한 개발 프로그램도 강의 리소스에서 다운로드 받을 수 있습니다.
다음 영상에서는 슬립 구조를 조작하는 법을 배워볼 거예요
거기서 봐요