또 다른 2진법 과제입니다
이건 한 바이트인데 난해합니다
그러니 천천히 자기 페이스대로 하세요
네 아까도 말했지만 며칠은 아니더라도 몇 시간씩 걸려서 개발 계획을 세우는
건 얼마든지 가능해요
네 이번 과제도 지난 과제와 같은 방식으로 접근해 볼 거예요
바이너리요 성격화 단계를 함께 진행할 거예요 프로그램을 어떻게 통제하는지 알아내는
단계죠 그럼 네가 버그를 찾아서 개발해 봐
목표는 이전과 같습니다 힙과
관련된 버그를 활용해 도전 바이너리에서 셸을 버리는 거죠
시작할게요. 네 챌린지 바이너리가
보이죠. pwntools 템플릿 스크립트도 있고요. 이 스크립트는
평상시 훈련부터 시작하죠
체섹과 바이너리의 보안 상태를 파악합니다
네 이번 과제는 모든 보호 요소를 포함한 것 같군요 렐로 스택과 카나리아
NX 포지션 인디펜던스도요
글리벡 버전 2와 연결됐어요 23번, 어떤 기술을 써야 할지 힌트를
줄 거예요
GDB에 바이너리를 로드하고 실행합니다
네 먼저, 이 프로그램은 구성 요소의 주소를 유출하지 않습니다 바이너리나
힙 libc 로드 주소도요
맞아요 지금까지 취약한 쌍성이 친절하게 libc와 때로 더 많은 주소를 알려줘서
다양한 기술을 배우는 데 집중할 수 있었어요
물론 제작 환경에서는 그럴 가능성이 거의 없죠
현대 시스템에 대한 개발은 종종 일종의 정보 유출이 필요합니다 이번 과제에서
그 인포리크를 위조하는 건 여러분에게 달렸습니다
네 번호표는 그대로예요 옵션
1은 덩어리를 최대 16개까지 요청할 수 있는데 우리 기준으로는 넉넉하죠 명심하세요
우린 방금 3개 이하로 탄피를 떨어뜨렸어요 ?
하지만 이 덩어리가 얼마나 큰지는 우리가 결정 못 해요
네 네 0x60 크기의 덩어리를 요청하는
거였어요
옵션 2는 0에서 인덱스로 덩어리를 자유롭게 시작할 수 있습니다 옵션 3은 할당된 콘텐츠를 편집할 수 있습니다
옵션 4는 할당된 양의 내용을 읽을 수 있습니다
자 그러니까 요약하자면 0x60 크기의 덩어리를 16개까지 요청할 수 있습니다 풀어 주고 읽고 작성할 수
있습니다
하지만 이 두 종족은 다른 종족과 미묘하게 다른 점이 있어요
네 네 "브레이스"
네 기본값으로 결과물이 지저분해질 수 있으니
검색 필터를 사용해서 'alloc'으로 끝나는 기능만 추적할 거예요 안 돼요!
PDF 문서는 말록의 주요 기능이에요 말록을 감싸고 있는 포장지
두어 개는 추가 기능을 제공하죠 옵션 1 lt레이스가 첨부된 메뉴에서 옵션 1을 선택하면 그 한 바이트
도전은 맬록 대신 메모리를 요청하기 위해 캘록 기능을 사용했다는 걸 알 수 있습니다
네 PDF 상태가 되면 메모리 요청을 할 때 맬록을 사용하고 발신자에게 돌려주기 전에 메모리를
0으로 설정합니다
이력서 네 프로그래머가 사용 전에 변수를 초기화하는 모습을 시뮬레이션합니다
그러니까 데이터를 많이 빼서 맬록 메타데이터를 유출하고 다시 할당해서 읽을 수 있다고
생각했다면 헛다리 짚은 거예요
네 폐기에 끼친 캘록의 효과를 간단히 보여드리죠 먼저 일부를 요청하고
쓰레기 데이터를 채운 다음 풀어줍니다 네 지금 검사해 보니 0x60 크기의
덩어리가 남아 있어요 그 첫 번째 네 글자는 물론 , 아셨죠?
그것만 빼면 내 데이터는 멀쩡해요
네 2진법 요청으로 돌아가서 0x60 덩어리를 다시 분석하고 다시 검사해 볼게요 거기 있었을
법한 말로크 메타데이터를 포함한 모든 데이터가 0으로 설정됐어요
크기도 고정되고 메모리도 0이라 쉽지
않을 겁니다
일단 도청기부터 찾아요 어딘가에
있을 거예요
그러고 나서 libc 주소 유출에 집중해요 글립코드를 사용하기 때문에 어떤 버전의 글립코를
쓰는지 알
수 있습니다 libc 런타임 주소에서 유출하는 어떤 부분의 오프셋을 빼서 libc 로드 주소를
제공합니다
libc 설정합니다 입력합니다 pwntools 스크립트의 특정 값에 주소가 입력되면
libc에 자동으로 업데이트됩니다 네 sym 기본 주소를 유출하면
정상적으로 진행할 수 있도록요 템플릿 스크립트는 그 방법의 예가 있어요
네 잊지 마세요 활용할 자료가 많습니다 힙랩 PDF 파일과 말록 시험판도 있죠
네 프롬프트가 뜨면 비디오를 멈추고 얼마나 큰 피해를 줄 수 있는지 보세요 정말 막혔거나
작업물을
확인하고 싶다면 비디오를
계속하세요 버그를 알려드릴게요
도청기는 찾았어요?
안 되면 몇 가지 시도를 해서 특이한 행동을 유발할 수 있는지 보죠
GDB에 바이너리를 로드하고 실행합니다
네 먼저 더블 프리인지 확인할게요
간단히 한 덩어리를 요청한 다음 두 번 연속으로 해제하면 되죠
두 배로 맛있는 벌레는 없어요
네
애프터서비스 어때요?
풀린 후에 청크의 데이터를 읽거나 쓸 수 있게 되면 맬록 메타데이터를 조작하거나 유출할
수 있어요 맞아요,
하지만 이 프로그램은 공짜 덩어리를 제대로 처리하는 것 같군요
그리고 그냥 아무렇게나 줄 순 없어요 흔적성 울록 메타데이터를 읽을 순 없죠 우리가
손쓰기도 전에 또 0이 될 테니까요
그럼 오버플로는 어때요?
패스트빈에 첫 번째 조각을 돌려달라고 하고 그 다음에 두 번째 조각을 요청할게요
그리고 나서 첫 번째 부분을 편집하고 88 바이트 이상의 사용자 데이터를 적습니다
0x60 크기의 사용자 데이터죠
GDB를 네 ? 네,
맞아요 네 두 번째 0x60 크기 필드가 0x59 또는 대문자 'Y'로 바뀌어
'vis' 명령을 혼란스럽게 합니다
버그를 찾았으니 이제 한 바이트 넘버로 어떤 컨트롤을 할 수 있는지 생각해 볼 필요가 있습니다
네 양이 많지는
않아요 1바이트는 맨 위 덩어리와 큰 차이가 없죠 예를 들면요
하지만 보시다시피 청크의 크기를 덮어쓰면 크기가 완전히 달라집니다
네 이렇게 하면 예를 들어 크기를 변경해서 자유롭게 할당된 다른 덩어리를 포개서
공간을 확보할 수 있습니다
이제 libc를 어떻게 유출할지 생각해 봐요 어쩌면 폐기물도
둘 다 유출할 수 있어요 부패를 통해서요 위쪽 덩어리는 무시하고 오버플로를 이용해 크기를 바꾸는
데 집중해요
기억하시죠? 네 "재고를 읽기"
그럼... 해방군 주소를 어떻게 올릴지 생각해 봐요 어차피 0x60 덩어리는 풀면
패스트빈에 연결되니까 패스트빈은 포워드 지점에 패스트빈 주소만 써요
네 이번 도전의 Pwntools 템플릿에 libc 유출에 대한 유용한
조언이
있습니다
다시 비디오를 정지하고 스스로 얼마나 진전이 있는지 보세요 힌트가 필요하면 여기로 돌아와요
잘 돌아왔어요
네 네 템플릿 2라고
하는데
네
해방군 주소를 압류할 수 있는 한 가지 방법을 보여주려는 거예요
네 4개의 덩어리를 요청했어요 a부터 d까지요 그리고 a를 편집한 거죠 한 바이트의
양을 이용해 0xc1 값을 이용해 가장 작은 바이트의 크기를 덮어썼어요
p8 사용을 보세요 () 여기서 1바이트만 썼어요
네 0xc0 크기를 고른 이유는 0x60 덩어리의 두 개를 합친 크기라서예요 모든
게 일직선이기 때문에 세그폴트나 완화 작용을 덜 일으키죠
됐어요 다음은 굵은 덩어리 B를 꺼냈어요 0xc0 크기의 덩어리로 처리해서 무체계 통에 넣을 거예요 ?
네
스크립트를 실행하겠습니다 GDB와 NOASLR
옵션으로요 ctrl+c로
깨고 힙을 검사하겠습니다 'vis' 명령으로요 어떤 효과가 있는지 보죠 , 좋아요
그리고 여기 보면 쓰레기 데이터와 B가 있는데 0xc0 크기의 덩어리가
무체중 상태와 연결돼 있어요 청크 d는 네 미리
사용 비트를 갖습니다
우리 행동 때문에 B 덩어리가 무체계화 빈에 연결됐어요 다른 방법으로는
불가능하죠 그 부작용으로 libc 주소가 무체계화 빈 링크 형태로 쓰여진
거예요
네 안타깝게도 안타깝게도 안 돼요
청크 c도 잊지 마세요
여전히 저기 있고 여전히 할당되어 있어요 읽고 쓸 수 있다는 뜻이죠
그... 생각해 봐요 우리에게 유리하게 나머지를 어떻게 쓸지 libc 주소 유출뿐
아니라 메타데이터 덮어쓰기도 설정할 수 있어요
비디오 멈추고 정보 유출에 도움이
필요하면 다시 와요
네 마지막 템플릿에 선을 더 추가했어요
리소스 섹션에서도 복사본을 얻을 수 있어요
3번이죠
네 제가 유일하게 바꾼 건 60x60 크기의 새 흙더미를 주문한 건데 그것도 같은
자리에 놓으려고 b라고 다시 이름 붙였어요
말록은 다음과 같은 행동을 합니다 패스트빈과
스몰빈에서 혈흔을 찾고 못 찾으면 무정제실에서 혈흔을 찾으세요 '패스트빈'에서 혈흔을
찾으세요
무체중에서 0xc0 찾으면 0xc0 스몰빈으로 분류해 주세요
빈 맵으로 돌아가서 0xc0을 남겨 첫 번째 부분을 프로그램에 할당하고 나머지는
무체계 상태에 연결해요
보여줍니다 네 사용자 데이터의 첫 4분의 2 쿼드는 앞뒤 포인터가
흐릿하게 메워졌습니다 "3/4
네 이 기회에 할당된 청크 C를 읽으면 돼요 주 경기장의 주소가 유출됐어요
대본에선 그것만 나와요
먼저 읽기를 이용해야 합니다 도움말은 C의 내용을 읽습니다 읽기 네 프로그램이 문자열 형식으로
제공하죠 그래서 다음 줄은
Python 조각 구문을
이용해 해당 데이터의 첫 4분의 1칼로드만 분리합니다 그런 다음 그걸 pwntools
u64와 함께 정수에 풀죠() 함수 ??
네 네 PDF와 Pwntools에서 함수를 푸는 것에 대해 더 보실 수 있습니다
네 네 안 돼요
네 우리가 할 일은 libc 공유 물체의 비체정화
정보를 그 주소에서 빼내는 거예요
네 네 폰툴과 가장 가까운 건 '메인_arena'
상징이죠 '메인_arena'
네 이 경우에는 메인 아레나 시작 후에 언소트빈 바이트가 0x58바이트예요
그 값을 하드코딩하면 돼요
네 네 원한다면 pwntools를 이용하세요. 제가 한
변수를 사용하지 말고요.
이 선이 앞서 말한 계산을 하고 libc를 설정해요 결과를 가진 주소요 libc 개체의
모든 기호를 업데이트합니다 libc
같은 걸 사용할 수 있죠 심 취약한 쌍성에 대항한 시스템처럼요
네 마지막 줄은 libc 주소를 기록해요 GDB와 상호 참조해서 성공했는지
확인하죠
디버깅 옵션으로 스크립트를 실행하고 힙을 살펴보겠습니다
거의 원래 상태로 복구됐어요 0x60 크기의 덩어리 4개로요
유일한 차이는 체감되지 않은 C자형 표면에 60x60짜리 표본이 남아 있다는 거죠
네 프로그램 창으로 변경하면 로깅 기능의 결과를 볼 수 있습니다 libc가 이 주소에서
로드됐다고 주장하죠
GDB로 돌아가서
네 ,
네 이제 libc를 유출했으니 다음 단계에서 libc
데이터 구조를 노릴 수 있어요 네 목표를 달성하려면 물이 많이 새야 하는지도 고려해야
합니다 물이 안정적일 때 하는 게 더 쉽거든요
그리고 잊지 마세요 데이터 덩어리가 겹쳐져서 메타데이터만
읽히는 게 아니라 덮어쓰기까지 합니다
한 유형의 힙 버그가 어떻게 다른 프리미티브로 바뀌는지에 대한 좋은 예입니다
예를 들어 처음에는 바이트 하나만 과다로 시작했지만 이제는 본질적으로 사용 후 무제한이 되었습니다 이
상황을 이용해서 이중 무제한 사용을 강요할 수도 있습니다
네 다음 단계 계획은 두 분이
짜세요 다시 비디오를 정지시키고 특정한 기술로 방향을 잡아야 하면 돌아오세요
정지하기 전에 많은 옵션이 있었는데요
합리적인 것을 찾기 위해 좀 줄입니다
네 더블 프리로 상황을 이용할 수 있다고
했죠 예를 들어 c 덩어리를 추가로 요청해서 즉시 패스트빈에 넣을 수
있어요 ?
좋아요 다음 패스트빈을 우회하려면 다른 덩어리를 빼야 해요 c 덩어리도 빼야 하고요
네 패스트빈 둡이 최선인지 모르겠어요
하지만 0x70 크기의 덩어리는 요청할 수 없습니다
이전 도전에서는 그 제한을 해결했으나 이번에는 한 덩어리만 요청할 수밖에 없습니다
이 접근법이 어렵거나 불가능할 수도 있습니다 ?
네 네 prev_inuse 플래그를 지울 수 있으니까요 하지만 이 프로그램이
힙 메모리에 정보를 저장하는 바이너리나 스택을 유출할 수 없으니 그걸
활용하기 힘들 거예요
그럼 오렌지 하우스는요?
네 이제 C 덩어리를 통해 무정체 상태의 메타데이터를 조작할
수 있어요
그리고... libc를 유출했으니 _IO_list_all 포인터를 노릴 수 있어요 흐트러진 빈 공격으로요
네 네 가짜 영상과 vtv를 만들 데이터를 충분히 통제하고 있어요 가짜
영상의 주소만 알면 파일 영상 포인터에 넣을 수 있죠
물이 엄청나게 새야 해요
이 시점에서 오렌지 하우스와 계속 일하거나 자신만의 기술을 선택하세요
어느 쪽이든 영상을 멈추고 어떤 기술을 선택할지 확인해 보세요
유출에 대한 조언이 필요하면 여기로 오세요
네 오렌지 하우스 기법을 쓸 거예요 물이 많이 새야 하거든요
제 취약점 스크립트에 그걸 할 대사를 추가했어요
이 강의 리소스에서 4번 템플릿을 다운로드하세요
네 리bc 유출 건은 한 줄로 다시 썼어요 읽기
힘들지만 이젠 뭔지 알잖아요 ?
내 계획은 메타데이터를 더 많이 c 덩어리에 쓰는 거예요 이번엔 힙 주소죠 메인 경기장의 정화되지
않은 곳에 유출한 것처럼요
네 리bc 유출을 나랑 다르게 접근했다면 다음 단계는 어떻게 하느냐에 따라
쉽거나 어려울 거예요
예를 들어 두 번째 덩어리를 무체중 빈과 연결하면 나머지 c 덩어리는
무체중 빈과 힙 주소를 갖게 되고 동시에 유출할 수 있어요
아까 하던 얘기를 계속하죠 libc를 따로 유출했어요
정리가 안 된 청크와 나머지 청크 C를 요청했어요
이 덩어리는 2번이에요
네 지금 2번을 꺼내면 0x60 패스트빈과 연결되겠지만
통에 제일 먼저 들어갈 테니 fd는 무효가 돼요
대신 다른 0x60 덩어리를 분리합니다
덩어리 A와 C2를
선택했죠
네 그럼 이제 나중에 아래쪽에 있는 c를 통해 정보를 흘릴 수 있어요
c는 아직 할당돼 있죠
@ 같은 조합의 read, slice, u64를 사용했습니다 유출을 위해
'힙'이라는 변수에 저장한 결과를요
네 이번에는 계산 안 해도 돼요 청크 A 주소를 유출할 거거든요 시작점에
있는 주소죠
마지막 행은 유출 힙 주소를
기록해 GDB와 상호 참조할 수 있습니다
디버깅 옵션과 스크립트를 실행해서 작동하는지 보겠습니다
GDB에 들어가서 'vis' 명령을 내립니다
여기 보시면 예상대로 a는 0x60 패스트빈과 연결됐어요 같은 패스트빈 머리 부분에
c2가 있으니 fd가
a를 가리키죠 , a를 가리키고 있어요 물론 C번 청크는 여전히 존재합니다 C2와 같은 공간에
있죠
네 힙 시작 주소를 보면 프로그램 창으로 이동해 힙을 성공적으로
유출했는지 확인할 수 있습니다
됐어요 이제 이 이진법과 오렌지 하우스를 이용할 수 있는 모든 정보를 얻었어요
네 네 혼란스러운 빈 공격으로요 libc가 유출됐으니까요 그리고
파일 스트림을 만들 수 있어요 유출이 가능한 포인터를 전부 설치해서요 유출이 가능해진 덕분이죠
네 이 템플릿을 잘 따르고 있다면 다음으로 해야 할 일은 힙을 무체계화된
메타데이터를 조작할 수 있는 상태로 되돌려 놓는 것입니다
영상을 멈추고 남은 인크리스티드 스텝을 혼자 해 보세요
무체중 공격부터요
원상 복구하기 힘들면 돌아와요 내가 도와줄게요
오렌지 하우스를 만들 준비가 됐으니 방향 감각을 잃게 만들어야 해요
네 유출되기 전에 할 수 있는 상황이었으니 다시 원상태로 돌려놔야 해요
네 다시 말하지만 저와 같은 할당 패턴을 따랐느냐에 따라 이 시점에서 다른 접근법이
필요할 수도 있어요
대본에 대사를 더 추가했어요
네 정리가 안 된 부분을 C로 겹쳐 놓기만 하면 정리가 안
된 메타데이터를 조작할 수 있어요
5번 템플릿의 복사본을 다운로드할 수 있어요 이 섹션 리소스에서요
좋아요 제일 먼저 패스트빈에서 2번과 1번 등을 떼어 냈어요 0x60
크기의 덩어리 네 개를 할당해서 초기 상태로 되돌리는 거죠
그리고 아까와 같은 방법으로 오버플로 버그를 활용합니다 청크 B의 크기 필드를 0xc1
값으로 덮어쓰기 합니다
네 b 덩어리는 무정체 상태로 풀어놨고
마지막으로 b 덩어리는 무정체 상태로 연결해서 c 덩어리를 겹치게 합니다
아직 할당된 상태죠
스크립트를 실행합니다 디버깅 옵션과 함께요 GDB를
입력하고 손상 정도를 평가하기
위해 'vis'로 힙을 검사합니다 , 그리고 스크립트를 실행합니다
예상대로 정리가 안 된 덩어리가 C가 사는 바로 그 장소에 있어요
네 정서불안 공격을 준비하려면
청크 C를 편집하고 정서불안한 청크 bk를 덮어쓰기만 하면 됩니다
오렌지 하우스를 완성하려면 혼란스러운 빈 공격으로 _IO_list_all
포인터를 공격해야 해요
네 정돈되지 않은 덩어리가 0x60 크기인지 확인해야 해요 제 경우엔 이미 됐고요
그래야 최종 요청을 할 때 0x60
스몰빈으로
분류할 수 있죠
그리고 마지막으로 가짜 줄을 만들어서 안 묶인 부분을 겹치게 합니다 그래야 물 내리는
검사기를 통과하죠 그리고 가짜 줄을 포인터로 연결해야 합니다
네 이건 분명 한 덩어리 이상일 테니 'dt 커맨드'로 각 필드의 균형을
확인하세요
그리고 GDB-fu를 이용해서 파일 스트림에 임의 주소를 캐스트하고 값의 정렬을 확인할 수도 있습니다.
네 네 당신의 가상 공간이 넘친다는 걸 기억하세요 진입 시 시스템으로 향해야 함 () 기능과 파일 스트림의 _플랙그 필드가
시스템으로 전달하고자 하는 명령을 갖고 있습니다
네 네 파일 스트림을 위한 공간을 확보할 수 있습니다
이제... 다시 영상을 멈추고 위조 파일을 조작해서 혼란스러운
공격을 준비해요
정렬이 안 되면 다시
와서 도와드릴게요
네 네 ? 네, 맞아요
이 6번 템플릿을 다운로드하세요
네 스크립트에 한 덩어리를 더 요청해야 합니다 제가 e라고 표시해 뒀죠 파일 스트림에
포인터를 달아야 합니다 ? 네
그리고 edit()를 이용해 문자열 'bin/sh'를 B 청크의 마지막 4분의 1칼로드에
적었습니다 제 파일 스트림의 _flag 필드를 형성하죠
청크 c를 편집했습니다 아까 만든 것과 같은 공간에 있는 청크 c를 덮어쓰기 위해 청크
bk를 _IO_list_all-16
주소로 대체했습니다 ??
네 편집을 통해 같은 편집실에서 _IO_write_base와 _IO_write_pointer 필드를 설정해
두었습니다 버퍼 플러싱 확인을 통과할 수 있도록요
모드 필드는 이미 처리했습니다 캘록 덕분에
차지하는 메모리를 0으로 만들고 있죠
네 마지막으로 마지막으로 오버플로를 저장했습니다
시스템에 포인터를 입력했죠 '용도 폐기물' 필드에요
이거면 소라 껍데기를 구해서 다음 호출 때 말록을 부를 수 있을 겁니다
여러분 우리가 마지막 요청을 하면 말록이 혼란스러운 곳을 수색할 겁니다 부디 부패한 bk를 0x60
스몰빈으로 분류하길 바라야죠 그럼 아이오리스트_all에 혼란스러운 bk 공격을 유발할 겁니다
?
그럼 말록이 유산할 거예요 정서불안 상태의 다음 덩어리가 검사에 실패하면 정화 작전이
시작되고 부패_IO_List_all 포인터를 따라 메인 아레나로 갈 거예요
네 메인 무대는 실패하면 좋겠네요 버퍼 플러싱과 체인 포인터는 0x60 스몰빈 bk를
가로지르며 가짜 파일 스트림을 따라갑니다 이 가짜 파일 스트림으로
다 됐어요 버퍼 플러싱 검사를 통과하면 소리가 가짜 저장소로 바뀌고 조개와
차가 완성됩니다
스크립트를 실행하겠습니다 디버그 옵션과 함께요 문제가
있으면 사후에 할 수 있도록요 깨서 '비스'를 써서 가짜 파일 스트림이 있는 힙을 확인할게요
아까 보여드렸던 GDB-fu를
사용할 수 있어요. 가짜 파일 스트림이 어떻게 생겼는지 보기 위해서요.
_IO_write_base와 _ptr 필드는 순서대로 보입니다 _모드 필드도 마찬가지고요
네 네 그리고 제 포인터에 따르면 물이 넘친다는 건 시스템에
정확히 맞는다는 거죠
내가... '정리 불가' 명령을 발동하면 _IO_list_all 포인터 주소를 출력해
안 그러면... 방향 감각을 잃은 공격도 제대로 정렬돼 있죠
오렌지 하우스를 위해 모든 준비가 끝났습니다
이제 말로크에게 마지막 요청만 하면 됩니다 행사를 시작하게 해 달라고요
하지만 프로그램은 계속됩니다
네 GDB 수치로 돌아오면 중단점도 세그폴트도
없고 조개껍데기 건의 지저분한 결과도 없습니다
좋아요 이제 마지막 반전이에요
왜 껍데기를 못 받았는지 곰곰이 생각해 보세요
우리 공격의 성공 여부를 파악하는 거죠
명심하세요 정서가 마비된 상태에서 공격받으면 판드버그는 덩어리가 정서가 마비된 상태와
연결됐는지 헷갈릴 수
있으니 명령의 결과를 그대로 받아들이지 마세요
영상을 멈추고 시간을 들여서 이 문제를 해결하세요 해결하거나 정말 해결이 안 되면 돌아와서
무슨 일인지 알아봅시다 이 영상의 마지막 부분에서요
무슨 일인지 알아냈나요?
요청할 수 있는 덩어리의 크기가
중요합니다
네 말록에게 마지막으로 연락했을 때 0x60 스몰빈으로 분류될 줄 알았어요 네, 0x60
스몰빈요
네 중요한 과정입니다 0x60 스몰빈의 bk가 체인 포인터를 형성하기 때문이죠 _IO_flush_all_lockp()
따라가는 기능
네 하지만 이번 도전에서는 0x60 크기의 덩어리가 필요합니다 그래서
마지막으로 말로크에 전화했을 때 분류하는 대신 0x60 크기의 덩어리를 할당받았죠
맞아요 연결 고리가 일부
풀려서 흐트러진 빈을 공격했지만 말록이 그걸 발견하고 빈을 찾는 걸 중단해서 중단
명령을 내렸죠 하지만 그런 일은 없었어요 그래서 프로그램이
계속 작동했던 거야
지금 프로그램을 중단하거나 한 덩어리를 더 요청해서 정상 참작을 한다면 예를 들어
_IO_flush_alllockp() 그래도 호칭은 되겠죠
하지만 0x60 파일은 스몰빈에 들어가지 않았기 때문에 파일 스트림이
겹치는 _체인 포인터는 다시 메인 스트림으로 돌아가죠 가짜
파일 스트림은 처리되지 않아요
이걸 어떻게 극복할까요?
요청 크기는 못 바꿔요 0x60
크기의 덩어리만 요청하거든요
그리고 프로덕션 환경에서 파일 스트림을 읽고 쓰거나 새 스레드 시작을 통해 다른 크기의
요청을 트리거할 수 있지만 이 바이너는 그런
컨트롤을 제공하지 않도록 디자인됐어요
분류해야 할 덩어리의 크기를 바꿀 수 있나요?
네 물론 그렇게 하면 다른 통으로 분류되겠죠 하지만 잠시
생각해 보자 0x60 스몰빈이 비었을 때 IO_flush_alllockp () 불이
붙으면
이중으로 연결된 통이 비면 fd와 bk가 통을 가리킵니다
네 _체인 포인터가 따라오면 처리될 다음 파일 스트림도 메인 아레나를
겹칩니다 오프셋만 다르죠
파일 스트림의 체인 포인터가 겹치지 않으면 주기가 계속돼요
네 이렇게 하면 완충기 변기를 막을 수 있어요 체인 포인터가 되는
통을 채우면 되죠
말로크에게 최종 결정을 내렸습니다
네 아직 안 쓰셨다면 지금 추가하시거나 강의 리소스에서 이 템플릿을 다운로드 받으세요 ,
스크립트를 디버깅 옵션으로 실행하고 GDB로 전환합니다
마지막 정지 전으로 되돌아간 거예요
혼란스러운 공격은 시작됐지만 아직 진행 중입니다
네 지문으로 '불량 파일 흐름의 포인터를 추적할게요' '0x60
스몰빈 bk 위에 있는 거요'
예상대로 주 경기장에 자리 잡고 있습니다
파일 스트림의 _체인 포인터가 겹치는 통을 찾아보죠
네 네 Arena 레이아웃
다이어그램을 PDF에 참조해 맞는 상자를 찾을 때까지 상자를
세면 돼요 , 그럼
네 맨 위가 보이고 마지막 잔해가 보여요
그다음이 정돈되지 않은
bk 그다음이 스몰빈 0x20 0x30 기타 등등 ? 일치하는 주소를 찾을 때까지요 0xb0
스몰빈 bk죠
그럼 다시 개발 스크립트로 돌아가서 위조 파일 스트림을 0xb0 스몰빈에 고정하는 부분을
정렬해 보죠 0x60 스몰빈이 아니라요
줄에 아주 작은 것만 추가하면 돼요 우리 파일 스트림의 _flag 필드에 "bin/sh" 문자열을
적는 줄에요 바이트 하나를
추가하는 거죠
그럼 청크의 크기를 0xb1로 맞출 수 있어요
네 자 이제 착취를 할 때 무정부 청크는 할당받지 않고 0xb0
스몰빈으로 분류됩니다 네 일단 중단하면 발동된 후 _IO_flush_all_lockp()
손상된_IO_alllist_all 포인터를 따라 메인 아레나로 갑니다 거기서는 하나가 아닌 두 개의 파일 스트림을 프로세스하고
두 번째 파일 스트림을 따릅니다 _체인 포인터로 가짜 파일 스트림을 확인합니다
그다음은 뻔하죠 어떻게 될지
뻔해요 그럼 착취를 해서 성공했는지 봅시다
우리가 소라만 벗으면 불평을 하는데 좋은 징조예요
프로그램 창으로 가면 드디어 셸이 있는 게 보입니다
물론 이 착취는 오렌지 하우스보다 믿을 게 못 되죠
생산 조건에서 실행하면
평균 성공률이 50%예요
네 마무리하기 전에 다른 방법이 있어요 더 우아한 방법이죠
? 네
잠시 편집기를 닫고 챌린지 바이너리를 GDB에 로드합니다
시작 글리벡에 '시작' 명령을 입력하세요 그다음
멀록 소스 코드를 입력하세요 , 다음을 입력하세요
네 이 코드 조각은 혼란스러운 검색 과정의 일부로
코멘트에서 말하듯 첫 번째 'if' 문이 현재 요청에 정확히 맞는지 결정합니다
네 정확히 맞는 덩어리가 무정리 상태 통에 배정됩니다
크기와 크기가 다른 통에 분류되죠
네 이 코드는 분류하기보다는 정렬에 더 신경 썼어요 착취가
실패했을 때요
네 네 말로크가 요청을 실제 청크
크기로 모은 결과죠 , nb는
예를 들어 3바이트라고 하면 'nb'는 0x20이라고 뜨죠
이 게임의 경우 바이너리 'nb'는 항상 0x60입니다
'사이즈'는 검사 중인 무분별한 덩어리의
크기를 뜻합니다 비교하기 전에 말록의 깃발을 떼서 방해받지 않게
합니다
네 하지만 덩어리 크기의 밭에는 깃발이 3개뿐이에요 네 번째
가장 덜 중요한 부분은 깃발도 아니고 덩어리에 기여하지도 않아요 네 쓰레기통을 수색할 때 비교하기
전에는
마스크를 벗지 않습니다 애초에 설정할 이유가 없으니까요
네 번째 0x60 덩어리를 가장 덜 큰 것으로 설정하고 크기를 0x68로 설정하면 prev_inuse
플래그를 유지하고 싶다면 0x69로 설정하면 0x60 크기의 덩어리를 요청할 때 정확히
들어맞지 않을 겁니다
그리고 더불어 각 통에 정렬하는 코드가 마스크를 벗습니다
구체적으로 크기가 작은 모든 나비를 회전시켜서 0x68 크기의
나비를 정확하게 0x60 스몰빈으로 분류하죠 ?
그럼 마지막으로 편집자를 불러 이 대체 전략이 성공했는지 알아보죠
오버플로를 통해 작성한 0xb1 사이즈 필드를 바꾸면 됩니다
0x68부터 0x6f까지 어떤 값이든 쓸 수 있어요
네 보통은 나중에 안정성 문제가 생기지만 지금은
착취의 마지막 단계라서 걱정할 필요가 없습니다 ,
생산 조건에서 네
안 돼!
그게 한 바이트에 대한 도전이었습니다
바이트 넘버로 셸을 구하는 데 성공했어요
게다가 그뿐 아니라 문제의 2진법도 현대적 보호 장치로 구성돼 유출과 libc
유출을 동시에 해결해야 했어요 게다가 한정된 수의 단일 장비만 요청할 수 있었는데 그게 이상하게
큰 덩어리로 변했죠
게다가 우리 힙 메모리가 할당된 칼로록 함수에 의해 0이 됐어요
네 도전을 완수한 걸 축하합니다 어려운 부분을 통과할 때 핸들이 필요하긴
했지만요 이로써
많이 배웠길 바랍니다 효과적인 취약점을 리뷰하고 싶다면 마지막 수정을 마지막 템플릿에 추가하거나
강의 리소스에서 주석으로 된 솔루션 스크립트를 다운로드할 수 있습니다
학습 자료와 도전은 여기까지입니다
이제 마지막 영상에서 각자 길을 갑니다