히랩랩 2의 첫 번째 활용 기술은 영혼의 집입니다
1편에 나온 의회의 병력과 함께 말록말레피카룸의 일부죠
네 다용도로 쓰이는 기술은 아니지만 다른 버그에 활용할 수
있어서 흥미롭다고 생각해요 네 Part 1에서 배웠던 맬록 내부
명령과 폰툴 함수들도 살펴보고
더 복잡한 것으로 넘어가겠습니다
개발자 환경 내에서 터미널을 열고 아까 추출한 HeapLAB_Part2
폴더로 들어간 다음 영혼 디렉터리로 이동하세요
네 영혼의 집이라는 이진법이 우리 목표물이에요 힙랩 1편에서처럼 메모리
파괴 버그가 있는 C#형 프로그램이죠
기억하시겠지만 타깃 바이너리에 대해 가장 먼저 알고 싶은 것은 보안 상태입니다
체섹과 함께 알아보겠습니다
네 체스섹을 보니 영혼의 집은 렐로 스택으로 지었더군요
카나리와 네크로스 완화제 네 완전한 렐로라면 임의로 프리미엄을 개발하면 프로그램의 절차나
연결표, 배열을 목표로 할 수 없어요 스택 카나리아는 스택 메모리 손상
버그가 강력하지 않다는 뜻이고 nx는 mprotect ROPS를 개발하지 않는
한 셸코드는
고려할 수 없다는 뜻입니다 이 과정에선 범위 밖이죠 ,
네 취약한 바이너리는 독립 실행이 안 됩니다 런타임에 주소를 알 수 있고 런패스에서
버전 2와 GLIBC가 연결되어 있습니다 30편은 tcache 지원 없이 편집됐습니다
네 이 설정에 대한 이유는 1부에서 말씀드렸는데요 지금 다시 짚어보겠습니다
2진법은 네 , 원시적인 걸 쓸 수
있죠
지위
독립성 부족은 불법 착취에 필요 없습니다
글립코 2 30은 글리벡의 최신 버전을 녹음할 때입니다 tcache 지원 없이 컴파일됩니다
아직 tcache에 대해 다루지 않았기 때문입니다
tcache가 있으면 글리벡 힙을 실행하기가 더 쉬워집니다
자 이제 이 프로그램의 취약점 완화에 익숙해졌으니 런타임엔
어떻게 작동하는지 보죠
그리고 영혼의 집을 GDB에 입력하고 '런' 명령을 실행합니다 명령어를 줄여서 'r'로 바꿀
수 있습니다 "r"
네 이런 디버깅은 aslr을 무력화합니다 하지만 지금은 이 프로그램을 어떻게 통제하는지 알아내는
데만 집중하죠
네 네 새 기술을 배우는 중이라 libc 주소와 기본값 힙 시작 주소가 유출됐어요
이 프로그램이 무례하게도 우리 나이를 늘리고 있어요
네 평소에는 이 프로그램이 말로크와의 직접 인터페이스인 척하지만
학생들에게 임의의 숫자를 묻는 게 임의적으로 느껴졌어요
32를 입력합니다 16진법으로 쉽게 식별할 수 있죠
사용자 이름과 쓰레기 데이터를 입력합니다
드디어 하이랩 1부에서 익숙한 메뉴가 나왔습니다 옵션 1은 말로크로부터 최대
8덩어리를 요청할 수 있죠
그걸 쓰면 요청 크기가 나오는데 작은 덩어리로 제한돼 있죠
네 1부 스몰빈에 대해 설명드렸던 것을 기억하실 겁니다 작은 덩어리는 0x20부터
0x3f0까지의 크기에 해당합니다
0x3f0의 최대 사용자 데이터는 0x3e8이나 1,000 바이트입니다
옵션 1을 다시 선택하고 최소 크기의 덩어리를 요청합니다 이제 쓸 데이터를 요청하는 창이
떠요 쓰레기 데이터를
보내죠
마지막으로 청크에 이름을 붙여주세요 저는 AAA라고 부를게요
네 메뉴를 보면 8개 중 1개가 할당됐어요 영혼의 집이 우리 데이터로
뭘 했는지 보죠
네 GDB에서 드릴 브레이크 ctrl+c로 하고 힙을 검사합니다 'vis_heap_chunks
command'로요 'vis'를 줄이죠
결과물을 보면 크기 필드 0x20의 최소 크기를 할당받았다는 게 나옵니다
그리고 데이터는 대문자 z가 그 덩어리에 복사됐죠 사용자 데이터
그럼 청크 이름인 대문자 A는? 스택에 저장됩니다 네 이번 힙랩 1부에서 멀록은 할당된 덩어리를
계산하지 않고 대신 요청한 프로그램에 따라 처리한다는 걸
배웠죠 ? 네
네 이 과정은 이 쌍성들은 제가 'm_array'라고 명명한 배열을 이용해 할당된 덩어리를
기록하고 하우스_스피릿 프로그램은 m_array를 유지합니다
Part 1에서 '프티프' 명령을 사용해 기억 속에 구조물을 배치했습니다
네 네 "NETFF"
네 백트레이스 패널을 보면 프레임이 2번임을 알 수 있습니다 '프레임' 명령을 사용하거나 'f'를 이용해
프레임 2로 변경하세요
좋아요, 이제 우린 주요 () 함수 프레임에 있어요 GDB가 로컬 변수를 인식해 이 프로그램의 m_array가
어떻게 배치됐는지 볼 수 있죠
네 8개의 '청크' 스트럭츠 배열로 각각 8바이트의 '네임' 필드를 갖고 있고 할당된
사용자 데이터에 포인터를 보냅니다
또한 이 배열이 '신포' 명령을 이용해 스택에 있는지 확인할 수 있습니다
네 m_array의 내용물을 검사합니다 'print'이나 'p' 명령으로요 첫 항목이
채워졌습니다 청크 이름이 있고 사용자 데이터로 포인터를 보냅니다 우리 데이터가 들어 있죠
자... 런타임 분석으로 넘어가서 '계속' 명령을 발령해보죠 기억하시겠지만 줄여서 'c'로
할 수 있습니다
다시 돌아와서 하우스_spirit 메뉴를 출력합니다 옵션 2는 할당된 무료 청크를 제공합니다
HeapLAB 1부에서도 그랬듯이 덩어리는 인덱스로부터 풀립니다 0에서 시작하죠
네 무료 함수가 어떻게 작동하는지 기억하시겠지만 청크 0을 풀어주면서 다시 정리해보죠 GDB를
ctrl+c로 입력하고 힙을 'vis'로 검사합니다
네 예상하신 대로 아까 요청한 0x20 덩어리는 '패스트빈'의 허가로 0x20
패스트빈으로 "통과되었습니다"
계속하고 다시 반환을 누르면 이번엔 메뉴에서 옵션 3을 사용합니다 1부에서처럼 우리의 목표는 영혼의
집 기술을 익힌 후에 그걸 이용해서 원시적인 글을
쓰는 겁니다
네 우리의 목표는 늘 그렇듯 이 바이너리의 데이터 섹션에 있는 짧은 x줄입니다
네 2진법은 기억하실 텐데요 비좌위 독립형으로
런타임에 타깃 주소를 알 수 있죠 ? 네
목표 데이터의 위치를 확인하고 이 2진법의 런타임 분석을 완료하죠 그리고 네 GDB로 들어가서 "ptype"
명령을 이용해 레이아웃을
보여줍니다 "Fptype"
네 'user' 구조는 처음 프로그램을 실행했을 때 채워야 했던 'age' 필드를 포함하고
잠시 후에 타깃을 추가합니다 마지막으로 앞서 채웠던 'username' 필드도 두 번째 공백 후에 채워야 합니다
네 'user' 스트럭츠를 시각화하려면 'dq' 명령을 이용해 스트럭츠 시작에서 22개의 사분 단어를 꺼내야
해요 'dq' 명령
네 네 그다음 타깃은 x를 0x58바이트로 표시하고
우리 사용자 이름인 y를 0x59로 표시하죠
?
네 '에이지' 필드를 의심하고 계시겠죠 네 조만간 가짜 사이즈 필드로 사용할 겁니다
하지만 너무 앞서가는군요 먼저, 프로그램의 버그를
찾을 시간을 드리죠
프롬프트가 뜨면 영상을 멈추고 뭘 깰 수 있는지 봐요
영혼의 집에서 도청 장치를 찾았다면 잘했어요
못 찾으면 걱정 마요 찾기 힘들 거예요
네 영상 시작에서 말씀드렸듯이 영혼의 집은 지중해와 무관한 버그를
이용할 수 있고 그 주제에
따라 이 프로그램의 버그는 스택 오버플로입니다 ?
네 혹시 못 봤으면 작동법을 알려 줄게요 영혼의 집을 GDB에 저장할게요 ? 네 실행하고
쓰레기 같은 걸 보내죠 age와 사용자 이름 값 옵션 1을 이용해 최소 크기의 덩어리를 요청합니다
가비지 데이터로 채우죠 그럼 덩어리 이름이 나옵니다 ? 네, 맞아요
여기서 물이 넘쳐요
기억하세요 이 프로그램은 스택의 배열에 청크 포인터를 두는데 사용자가 준 8바이트
이름 앞에 각각의 포인터가 있습니다 만약 8바이트 이상인 이름을 보내면 청크 포인터로
넘쳐 넘칠 겁니다
네 GDB를 길들여보면 피해가 얼마나 되나 보죠 () 함수의 프레임으로 전환하면 첫 번째 m_array
엔트리의 내용을 검사할 수 있습니다 오버플로 버그가 포인터를 큰 덩어리에 덮어쓰게 해줬죠
네 말로크는 할당된 덩어리를 기록하지 않기 때문에 메타데이터를 손상시킨 게 아니라
프로그램 데이터만 손상시켰죠
이 포인터를 읽기와 쓰기 작업에 사용할 수 있다면 아주 강력한 원시 상태일
겁니다 말로크와는 아무 상관 없지만요
네 하지만 이 시나리오에선 할당 직후에만 작성할 수 있습니다
손상 후 이 포인터로 할 수 있는 건 무료란 거죠
네 이게 영혼을 타락시키는 집의 기초예요 이 표시를 무료 () 기능으로
전달하죠 포인터를 어떻게 조작하든 상관없어요
네 스택 오버플로를 이용했지만 메모리 손상은 다른 곳에서 쉽게 발생할 수 있습니다
,
네 영혼의 집을 이용하는 건 이론상 간단해요 민감한 데이터를 겹치는 것만
분리해서 그 가짜 데이터를 할당하면 그 데이터를 읽거나
쓸 수 있죠
? 네
패스트빈 둡이라고 생각하세요
네 가짜 청크를 bin에 연결하는 거예요 손상된 bin 메타데이터를 손상시키는 대신 합법적으로
bin에 풀어줍니다
곧 보시겠지만 이 점에는 장단점이 있어요
좋아요 이제 프로그램의 버그를 파악했고 대략적으로 뭘 할 건지도 알았으니 폰툴
라이브러리로 영혼의 집을 만들어 보죠
pwntools_template를 복사하세요 py 스크립트, 복제 pwn이라고 부르지 않는 걸 기억하세요 네 그리고 선택 편집기에서 열어보세요
1부에서 그랬듯이요 전 Vim을 사용하겠지만 여러분은 아무 편집기나 IDE나 사용할 수 있어요
이 인크리스틱 템플릿의 형식은 변하지 않았어요
파이썬 3를 이용합니다 그리고 pwntools 라이브러리를 이용합니다 그리고 여전히 도우미 함수를 가지고 있습니다
빠르게 하기 위해 작성했습니다
이 대본에는 말록과 무료 기능이 있습니다
Mloc 하우스 오브 스피릿 프로그램 메뉴의 옵션 1번 기능이 포함돼 3개의 인수가 필요합니다
요청하고 싶은 청크의
크기 입력하고 싶은 데이터 그리고 청크의 이름이죠 요청한 덩어리의 인덱스를 반환합니다
이 프로그램은 청크를 최대 8개까지 요청할 수 있습니다
무료. 네 ????????
네 스크롤 하단을 보면 익숙한 레이아웃이 보여요 libc 유출은 'libc'
대상을 채우는 데 사용돼 기호들에 빨리 접근할 수 있고 유출이 '훔' 변수에 기록돼 있어요 ?
이 점선 사이에 착취물을 넣을 거예요
네 현재 스크립트는 'age'와 'username' 필드를 임의의 값으로 설정하고 각 도우미 함수의
사용을 예로 들어봅니다
여기 여기 보면 최소 크기를 요청하는 데 사용됩니다 쓰레기 데이터와
y를 채우고 이름 필드를 a로 채우죠
그 후에는 무료 도우미를 통해 동일한 부분을 풀어줍니다
시작은 'EXAMPLE' 헤더와 free() 도우미 함수 호출로 시작합니다
네 아시다시피 스크립트를 실행하면 영혼의 집이 시작돼요 우리가 말한 입력값을 보내고 io로
컨트롤을 우리한테 돌려줘요 상호작용
기억해야 할 것은 pwntools 스크립트, gdb와 NOASLR 옵션을 넘길 수 있다는 겁니다 GDB를
타깃 프로세스에 연결하고 ASLR을 해제해 디버깅이 쉬워지죠
지금 해 보죠
GDB 창이 있는데 alt+로 프로그램 창과 사이를 벌릴 수 있죠
네 스크립트가 GDB 창에서 무엇을 했는지 봅시다 ctrl+c를 누르고 'vis' 명령이
프로그램의 기본 힙을 검사합니다
네 예상대로 0x20 크기의 덩어리를 요청한 대로 사용자 데이터에 Y를
채웠습니다
네 정말 관심 있는 건 스택 스위치예요 메인 () 함수의 프레임에 첫 m_array
엔트리를 프린트합니다
'이름' 필드에 A가 있고 0x20 크기의 덩어리에 포인터를 그려요
넘쳐흐르는 벌레가 사는 이 '이름' 들판의 인구죠
좋아요, 아까 사용한 'dq' 명령을 실행하세요 타깃 데이터에 대한 메모리 레이아웃을
상기시키려고요 타깃 데이터를 겹치는 가짜 덩어리를 빼야 한다는 것도 잊지 마세요
네 네 우린 그게 필요해요 아시다시피 무료 수술에선
덩어리 크기가 운명을 결정하니까요
스크립트를 수정할 것입니다 GDB를 종료하거나 "quit" 혹은 ctrl+c로 종료하고 에디터로 돌아갑니다
네 이름 변수 내용물은 프로그램이 청크 A의 이름을 정하라고 했을 때 나오는 거예요 a에 부착하는
건 m_array의 첫 번째 엔트리에 저장된 청크 포인터로 흘러 넘칩니다
'user' 스트럭트의 주소를 보낼게요 타깃 데이터를 갖고 있는 곳이죠
Pwntools 팩을 사용할 수 있습니다 주소를 문자열로 포장하는 기능 그 너비는 대상 바이너리의
아키텍처에 의해 결정됩니다
이 경우엔 p64와 동등하죠 이 경우엔
둘 다 쓸 수 있습니다
포인터를 덮어 쓸게요 네 사용자 데이터에 포인터를 덮어 쓰고 있다는 걸 기억하세요
free()가 호출되면 맬록이
16을 빼서 헤더 찾습니다 ?????????
맞아요 가짜 덩어리를 풀어준 대사도 다시 넣죠 가짜 덩어리를 풀어줘서 영혼의 집이
생겼으니까요
네 크기 필드는 그냥 두죠 지금은 특정 값으로 설정돼 있어요 변경하기 전에 제가 강조하고
싶은 거죠 안 돼요
대신 스크립트를 현재 상태로 실행하죠 GDB와 NOASLR 옵션으로요
네 잠깐 멈추면 익숙한 역추적이 보일 거예요 말록의 착취 완화 작용을 암시하죠
네 우선, 우리 덮어쓰기가 성공했는지 확인합니다 메인 프레임으로 변경해서요() 함수의 프레임 이제
프레임 5죠 첫 번째 m_array 엔트리의 내용을 프린트합니다
gdb의 주석을 보면 사용자 데이터의 주소를 가지고 있던 포인터가 이제 "user"
스트럭트 + 16을 가리킨다는 것을 알 수 있습니다 계획대로요 네 네 'age'가 가짜
청크 크기로 표시됩니다 의도한 대로요
, 좋아요
글리벡이 왜 중단시켰을까요? 판드버그의 '말록_청크' 명령으로 말록이 가짜 청크를 어떻게
생각하는지 알 수 있어요
사이즈 필드는 0x6f예요 전에도 가짜 덩어리로 0x7f를 쓴 적이 있죠 네 1단계 실험에서는 가짜 0x7f 덩어리를
할당해서 말록 갈고리를 덮었습니다 패스트빈덥 기술도 익혔죠
왜 0x6f는 작동하지 않죠?
'멀록_청크' 명령이 가짜 청크의 깃발도 인쇄했어요
우리 사이즈의 광속이 0x0f라면 별로 중요하지 않으니까요 is_MAPPED 플래그를 포함해 모든 깃발이
설정됐습니다
멀록은 변수보다 큰 요청을 받습니다 'mmap_reshold'라는 변수죠 요청은 경기장이
아닌 글리벡 mmap를 통해 서비스됩니다 궁금하면 mmap에 대해 맨페이지에서 더
읽어볼 수 있고 멀록 파라미터에서 'mmap_thholdhold' 변수를 찾을
수 있는데 pwndbg의
'mp' 커맨드로 버릴 수 있어요 토끼의 집 기술에서 mmap 한계점을 더 알아보겠습니다
네 일단 mmap로 할당된 양이 is_MAPPED 플래그라는 것만 알면 됩니다 네 네 아레나로 다시 연결하는 대신
글립벡의 문맵으로 청크를 풀어줍니다
'컨텍스트 백추적' 명령을 발령하면 프레임 4가
말록의 문맵_() 기능과
일치합니다 가짜 청크를 풀려던 거죠 ?
네
얼라인먼트 확인에 실패했네요 프레임 4로 바꾸면 볼 수 있죠 '컨텍스트 코드' 명령도 발효하고요 ? 네
체크를 통과했더라도 이 코드 경로는 쓸모없어요 아레나에 Fake
청크를 링크해 나중에 할당해야 하니까요
네 영혼의 왕가가 부여한 첫 번째 제약입니다 패스트빈 둡과 비교하면
가짜 청크의 크기에 명확한 표시가 있어야 합니다
편집기로 돌아가서 크기 값을 수정해 보겠습니다
네 네 안 돼요!
0x6f를 0x6d로 바꾸면 다른 건 그대로 두고 IS_MAPPED 깃발은 확보할 수 있어요
네 기억나게 해드리자면 PDF '말록 인터널' 섹션의 '덩어리'
헤더에 자세히 나와 있어요
네 가짜 크기 필드를 업데이트했으니 다시 해 보죠 GDB와 NOASLR 옵션으로 스크립트를
실행하세요 ,
멈춰야 해요 네 이번에는 백추적 패널에서 문제가 있는 곳은 free_((기능 자체입니다 구체적으로
아레나_knknknknkn
네 히랩랩 1부에서 공연장이 두 종류라는 걸 기억하실 겁니다 메인 아레나로
글립크의 데이터 섹션이 있고 메인 아레나로 안 쓰는 건 말로크가 다중 응용으로 만들 수
있죠
네 주요 무대가 아닌 무대는 런타임에 역동적으로 만들어지기 때문에 말로크는 상징을 이용해 해결할 수 없습니다 , 그래서...
네 대신 새로운 장소와 그에 상응하는 'heap_info' 스트럭트를 만들어
특정 정렬로 매핑되게 합니다
네 말록은 마스크를 써서 비주거 지역을 찾아 그에 맞는 정보를
찾습니다
이겁니다 a 경기장을 연결하기 위해 free() 기능을 확인합니다 비메인_ARENA
깃발로 '멀록_청크' 명령이 보여주는 결과물은 fake 청크에 설정됩니다 안 돼!
네 공짜면 비 메인_ARENA 깃발 세트 청크를 메인 아레나에
연결하지 않고 주소를 가리키는 겁니다 반올림해서 값이 훨씬
낮아지게 청크를 찾는 거죠
맞아요 물론 이 가짜 덩어리는 경기장 소유가 아니라서 떼어내려고 하면 말록이
지도에 표시되지 않은 주소와 세그폴트 주소로 가요
어떤 경우에는 비 메인_ARENA 깃발로 가짜 아레나를 제공해 혼란을 일으킬
수 있지만 우리 경우엔 그냥 지우는 게 더 쉽죠
편집기로 돌아가 'age' 변수에서 0x6d 값을 0x69로 치웁니다
네 이제 IS_MAPPED와 비메인_아레나 깃발은 깨끗합니다 사용 전 깃발과 사용하지 않은 깃발만 남았죠
4등으로 덜 중요한 세트죠
다시, 일반적인 옵션으로 스크립트를 실행합니다
다시 한번 놀라움을 금치 못합니다 좋아요, 네 프레임으로 전환하죠 프레임 4요 '컨텍스트
코드'를 써서 뭐가 잘못됐는지 볼게요 안 돼요
네 네 ? 네, 프로그램 창에요
네 말록의 아리송한 오류 메시지를 보면 어떤 감형과 관련이 있는지 알
수 있어요 '감형' 부분 아래 헤더에 있는 '감형'을 확인하면 되죠 , 히댑랩 PDF에서요
네 디버거 창으로 돌아가 보면 Fake 청크가 이 체크 중 하나에 실패했어요 첫 번째도
아니고요 크기가 최소 값보다 크다는 걸 알거든요 ? 네
네 두 번째 확인 이 크기에 비해 별로 중요하지 않은 물체의 존재를 포착하기
위한 장치입니다
네 다시 원점으로 돌아왔네요 편집기로 돌아가 age 변수를 0x61로 설정합니다 prev_inuse
플래그를 제외하고 중요하지 않은 nybl은 제거합니다
일반적인 옵션으로
스크립트를 실행하세요
백트레이스 네 자유로운 사회에서 착취당하는
걸 참아야 했죠 절차는 알죠? 무료()로 전환 프레임과 '컨텍스트 코드'를 입력해요
이번엔 오류 메시지가 '다음 크기는 무효'예요
'리스트 4245'를 치면 이전 수표를 볼 수 있어요
네 말록의 정신 건강 검사 중 하나입니다 하지만 빼낸 덩어리를 수술하는 대신 남은 덩어리를
검사합니다
그 덩어리가 울타리보다 작거나 1부에서 다뤘던 av-system_mem보다 크면 감소가
촉발됩니다 그럼 감화되는 거죠
네 아까 'dq' 명령을 다시 실행하면 가짜 청크가 null인 후의 크기 필드가 유지된다는 걸
알 수 있죠
네 다행히 가짜 덩어리를 0x80으로 바꾼다면 'username' 변수에
타깃 데이터의 다음 쿼드에 걸쳐 적당한 다음 사이즈 필드를 제공할 수 있습니다
편집자에게 돌아가시면 그렇게 하죠
시작할게요 가짜 덩어리의 크기를 0x61에서 0x81로 늘려서 'username' 필드에 도달하게 합니다 'uername' 필드에요
네 이 시점에서 prev_inuse Flag 셋을 유지해도 되지만 그럴 필요는 없어요 이 덩어리는 패스트 덩어리로
취급되므로 prev_inuse
Flag는 무시됩니다
네 다음 'username' 변수를 수정합니다 3개의 안쪽 단어 다음에 적당한 덩어리가 있어야
합니다 ?????? 0x11과 av-sy시스템_mem1 사이의 어떤 가치든 이용할 수 있습니다
저급 나비는 유효하지 않아도 돼요
네 이렇게 변경한 후 평소 옵션으로 스크립트를 실행하면 다행히도 gdb는 멈추지 않습니다
,
네 네 안 돼, 안
돼!
네 '유저' 메모리 덤핑이 우리 셋업과 위조 크기 필드를 보여줍니다
네 이제 말로크로 가짜 덩어리를 요청해서 표적 데이터를 덮어쓰기만 하면 돼요
마지막 부분을 스크립트에 추가해보죠
편집자에게 돌아가세요 통화 후 무료로 말로크에 전화를 추가하세요 가짜 0x80
크기의 덩어리를 요청합니다
명심하세요 네 ??? 네
네 64바이트짜리 가비지 데이터를 보내 fake 청크의 사용자 데이터와 대상 데이터 사이의
간격을 메웁니다 그다음 쉽게 알아볼 수 있는 문자열로 타깃 데이터를 덮어쓰기 합니다
마지막으로, 이름을 입력해야 합니다 어떤 값이든 가능합니다
실행합니다 완료되면 개발 스크립트를 생산 조건에서 실행하세요 gdb와 NOASLR 옵션 없이요
반환을 눌러 프로그램 메뉴를 보고 옵션 3을 눌러 타깃 데이터를 출력합니다
영혼의 집 기술로 임의로 프리미티브를 작성했다는 걸 확인시켜 주죠
요약하자면 이 바이너리에 버그가 있어 포인터를 덮어쓸 수 있었죠 free() 함수로
넘어간 포인터요
버그가 저장소에 있긴 하지만 어디서든 발생할 수 있죠
여기... 이 버그를 이용해서 포인터 대신 가짜 청크의 주소를 넣었어요 목표물 데이터를 겹치게
준비했죠
네 이 가짜 덩어리는 아주 엄격하게 제한돼 있어요 분명하게 표시해야 합니다 그렇지
않으면 멀록이 가짜 덩어리를 주 경기장에 연결하지 않고 풀어 버리려 합니다
안 돼 깃발도 깨끗해야 해요 안 그러면
말록이 존재하지 않는 곳을 찾아 나설 테니까요 안 돼요
네 크기에서 네 번째로 작은 부분은 반드시 비워야 해요 안 그러면 정상 참작이 될 거예요
네 마지막으로 말록의 몸집을 뛰어넘는 가짜 크기 필드를 설치합니다 가짜 덩치를 던진 후에 정신 감정을 해야 합니다
,
네 일단 찾기만 하면 아니, 지금 이 경우엔 크래프트-우리 Fake 청크를 메인 아레나로 자유롭게 풀어줄
수 있어요 그걸 다시 요청해 대상 데이터를 덮어쓸 수 있죠 안 돼요
네 영혼의 집은 다재다능한 기술은 아니에요 최소 2사분어드는 통제해야 해요
목표 데이터의 양면으로요
하지만 중요한 건 무중력 버그를 이용할 수 있다는 거죠
네 이 기술을 다시 보고 싶으시면 주석화된 개발 스크립트를 다운로드하세요
네 다음 단계로
넘어가기 전에 가짜 덩어리가 다른 이진법으로 0x80 패스트빈을 통과했다는 걸 알아두세요 두
크기의 필드를 나란히 놓을 수 있다면 어떤 크기든 쓸 수 있어요 ,
더 많이 필요하다면요?
그러면 처리하는 데 있어서 자유로움과 제약이 더 많아질 겁니다
네 예를 들기 전에 지금까지의 공격 내용을 복사하거나 계속 수정할 수 있습니다
,
준비되면 작은 덩어리를 넣은 영혼의 집으로 가요
'age' 변수를 수정해서 0x81에서 0x91로 크기를 바꿔 줍니다
네 이건 '정상' 크기예요 무정자빈 삽입이 가능하죠 네, 무료로요
prev_inuse 비트 세트가 없다면 지금 설정하세요
네 네 링크 해제하는 위험한 방법을 1부에서 보셨을 겁니다 느린 덩어리에 사용 전 표시를
명확히 하면 말록이 이전 덩어리와 결합합니다
네 이 경우엔 prev_size 필드를 제공할 수 없을 뿐 아니라 가능하다 해도 안전한 링크를
풀어야 하고 크기 vs prev_size 확인을 만족시켜야 합니다 그럼 우리 공격에 엄청난
복잡성이 가해지죠 ,
Prev_inuse 비트셋에 두세요
다음 용도로 신속 검사와 정상 체온 검사를 합니다
네 Fake 청크 사이즈를 바꿨으니 'username' 변수를 수정해야 합니다 두 번째
크기 필드에 맞추기 위해서요 체크를 통과하려면 처음에 안쪽 4괄호를 2개 더 추가하면 됩니다
네 이 크기 필드의 prev_inuse 비트도 지우겠습니다 잠시 후 확실히 할 점을 위해서요
글리벡의 버전을 보세요 2번과 연결되어 있어요 30세, 무체제빈 검사에서
다음 크기 정신 상태도 확인합니다
그리고... 네 "마지막 요청: 가짜 덩어리" 이 전화에서
0x78을 0x88로 대체하세요
스크립트를 GDB와 실행하세요 ASLR 옵션은 없습니다
예상대로 GDB는 잠시 멈춥니다
지금쯤은 뭘 해야 할지 알겠죠 더블 프리 경감도 일어난 것 같고요
1부에서 봤던 패스트빈과 비교하면 이중으로 무료입니다
이것은 prev_inuse 플래그를 확인합니다.
깃발이 깨끗하면 우리가 옮기려는 땅덩이가 이미 빠져나간 거예요
편집자에게 돌아가셔서 최종 수정 사항을 알려주세요
거의 다 됐습니다 2차 크기 필드를 바꾸기 전에 고려할 것은 fake 청크의 prev_inuse 플래그를
설정해 놓았습니다 뒤로 통합되는 것을 방지하기 위해서입니다
하지만 전방위 통합은요?
연결 해제 네 , 계속해서요!
그럼 앞으로 더 강력해질 거예요
가장 쉬운 방법은 3분의 1 크기의 가짜 밭을 만드는 겁니다
네 2번 크기의 들판을 울타리 덩어리로 대체하고 사용 전 깃발을 꽂는 걸 잊지 마세요 더블 프리
감형을 피하기 위해서요 그런 다음 안쪽 글자를 추가하고 또 다른 울타리 기둥 덩어리를 추가합니다
이것도 prev_inuse 깃발 설정이죠 이번에는 정화를 피하기 위해서입니다
네 네 prev_inuse 플래그가 설정돼 있는 한요 그럼 메모리에서
찾을 가능성이 커지죠 우리가 직접 만드는 대신에요
이제 개발 스크립트를 실행해 봅시다. 이번에는 GDB 옵션만 가지고 해 볼게요.
네 이번에도 별다른 변화가 없는 것 같네요 alt+를 프로그램 창으로 옮기고 옵션3를
선택합니다 이로써 이번에는 가짜 작은 덩어리를 이용해 프리미티브라고 임의로 썼다는 걸 확인했습니다
, 하우스 오브 스피릿을 이용해서요
네 메모리에서의 셋업이 어떤지 보고 싶다면 디버거 윈도우 브레이크와 ctrl+c로
바꾸고 'dq' 명령을 이용해 '유저' 스트럭트에서 메모리를 버립니다 ,
네 가짜 청크 들판도 있고 울타리 기둥도 있고 전면 보초도 여기 있어요
네 하우스 오브 스피릿에서 가짜 청크를 쓰는 건 패스트 청크 플러스를
쓰는 것과 같죠 가장 덜 중요한 3사분자를 찾아야 해요
일반 덩어리를 쓰면 장점은 더 많은 크기를 수용할 수 있고 나머지도 쓸 수 있다는 거죠 즉,
할당하기 위해 가짜 덩어리의 정확한 크기를 요청할 필요가 없어요
맞아요 영혼의 집에서 일반적인 덩어리를 쓰면 안 되는 게 하나 있어요 다음
명령은 맬록 소스 코드 일부를 인쇄해 다음 파편이 경기장 밖으로 나가는지
확인하는 것으로 나타난다
네 자 이제 패스트 청크는 면제지만 이 수표는 낙제해야 하지
않나요? ? 아니요,
네 가짜 정상적인 뼈와 다른 뼈는 더미에 닿지 않았습니다
코드를 잘 읽으세요 다음 주소가 맨 위 것보다 큰지
같은지만 확인하면 돼요
그 아래 주소는 어떤 것이든 허용된다는 뜻이죠 작성 가능한 부분도요
네 유령의 집에서 가짜 패스트 덩어리를 쓰면 원하는 곳에 있을 수 있지만
가짜 일반 덩어리를 쓰면 주 경기장의 끝자락 아래에 주소가 제한됩니다
네 예외는 기억력 압박으로 경기장이 비연속적으로 변하면 이 과정에선
못 볼 거예요
네 원하신다면 강의 리소스에서 사용할 가짜 일반 스크립트가
있습니다
그러면 이렇게 엄격한 제한을 받는 기술을 어떻게 활용해야 껍데기를 얻을 수 있을까요?
다음 영상에서 함께 알아보도록 하죠