네 말록의 내부를 익혀서 가장 먼저 활용할 기술을 배워볼 겁니다 힘의
집입니다
자 이제 말로크는 기능과 메타데이터의 집합체예요 그 많은 메모리를 프로세스
쪽으로 분배하는 거죠
그리고 오늘날 우리가 신경 쓰는 기능은 두 가지입니다
말록은 힙 메모리를 요청하는 기능과 그걸 재활용하는 무료 기능이죠
네 네 맬록이라는 함수가 동적 메모리 할록에서 힙 메모리를 요청할
때 사용됩니다 맬록이라고도 하죠
하지만 최소한 단순한 기능이죠
단일 인수를 가져옵니다 메모리 크기로 원하는 만큼요 그리고 같은 양의 메모리를 가져다 줍니다
혹은 조금 더 많은 양을 원하는 대로 할 수 있습니다
그리고 맬록을 통해 힙 메모리를 요청하는 걸 시각화하기 위해 데모 바이너리를 디버그하겠습니다
개발자 환경에서요 터미널을 열고 다운로드한 힙랩 폴더로 들어가
하우스 오브 포스 디렉토리로 가면 이진수와 스크립트 모음이 보입니다
GDB 아래에 있는 'gdbdb 데모'에서 이진법을 디버그할 것입니다
네 GDB가 시작되면 메인에서 브레이크 포인트를 설정합니다 '브레이크 메인' 기능과 함께요 줄여서
'b 메인'으로 할 수 있습니다
'그리고 표적 바이너리에 '실행'이나 'r'을 붙입니다'
어서 오세요
네 화면에서 많은 일이 벌어지지만 현재로선 소스 패널만 신경 쓰고 있어요
세 번째 밑에서부터 pwndbg가 다른 정보를 인쇄하는
걸 막기 위해서요 소스 코드를 단계별로 거칠 때마다 '텍텍스트 섹션 설정 코드' 명령을 발부합니다 소스 코드로만
출력을 제한하는 거죠 디버깅 세션의 나머지 부분을 위한 것입니다 소스 패널을
프린트하고 싶다면 '컨텍스트' 명령을 이용할 수 있습니다 소스 패널을 보면 프로그램이 하는 일이
전부 parap 메모리를 요청하는 것입니다 paroc 함수를 여러
번 사용해서요 첫 번째 요청은 9바이트로 'a'라는 변수의 반환 값을 저장합니다
프로그램을 시작하기 전에 쓰레기 더미부터 살펴보죠
네 네 상단에 있는 전설에 따르면 힙은 파란색으로
칠해져야 합니다 하지만 명령 출력에는 파란 텍스트가 없습니다 "패스킷"
말로크는 필요에 따라 메모리를 구성하려고 중심부에서 요청하지 않으니까요
네 'next' 명령을 사용하세요 'nxt'로 줄일 수 있습니다 말로크에게
9바이트로 첫 요청을 실행합니다 네 네 굵게 인쇄되어 화살표로 표시하고
있습니다 네, 맞아요
네 좋아요 이제 안
돼요!
135,000 바이트가 조금 넘죠
이 영상은 우분투 18에서 찍혔습니다 04 VM은 다른 OS를
사용하거나 완전 백업에서 실행된다면 이 값들은 다를 겁니다
네 다음 힙 메모리를 검사합니다 'vis_heap_chunks' 명령을
이용해서요 줄일 수 있는 'vis'입니다 네 만약 여러분의 출력이 제 것과 다르다면
걱정 마세요 단말 컬러 설정이 다를 수도 있으니까요
내 경우에는 청록색으로 물든 부분이 말로크에게 처음 요청한 부분의 9바이트예요
네 'p'를 치면 확인할 수 있어요 저 호출에서 나온 반환값이 이 덩어리의 '유저
데이터'의 첫 4분의 1칼로리까지 간다는
뜻이죠
먼저 눈에 띄는 것은 9바이트 이상이라는 것입니다 정확히 24바이트짜리 4개 단어죠
말록이 제공하는 최소 입 크기로 만든 겁니다 네 네 말록은 최소한의
양을 반환합니다
맞습니다
네 제공된 것은
최소 청크 크기에 24바이트 사용자 데이터였습니다
네 이 필드가 뭔지 궁금하실 수도 있어요 첫 번째 사용자 데이터 전의 필드요 하지만 여전히 동일한
부분이죠
네 네 말로크는 인라인 메타데이터를 사용합니다 즉, 스택 메타데이터를 저장된 기본
포인터와 반환 주소가 스택에 저장되는 것과 같습니다
말로크는 힙 메타데이터를 힙에 저장합니다 특히 이 경우엔 크기 영역이죠
네 네 크기 필드도 포함됩니다 사이즈를 나타내는
거죠
그래서 이 덩어리의 경우 사용자 데이터에 24바이트 더하기 8바이트 크기는 32 또는 0x20바이트입니다
하지만 여기 0x21 값이 있어요
말록의 몸집이 16바이트씩 커지기 때문이죠
네 예를 들어 'next'를 이용해 정확히 24바이트의 힙 메모리를 요청하면
'vis'를 보면 0x20 크기의 청크인데 정확히 24바이트의 사용자 데이터가 들어있죠
네 이제 이제 'vis'는 다음 덩어리를 의미합니다 0x30이고 40바이트의
사용자 데이터도 있습니다
네 네 국기를 나타내는 데 사용되거든요
,
이 경우 가장 덜 중요한 게 prev_inuse
플래그를 나타냅니다 네 prev_inuse Flag는 간단히 말해 아까 나온 하위 메모리의 인접한 청크를
프로그램이 사용한다는 뜻이에요
이 모든 덩어리가 사용되기 때문에 모든 전v_inuse 플래그가 설정됩니다
첫 번째 덩어리의 prev_inuse 플래그는 항상 설정됩니다 왜냐하면 이전 덩어리가 없거든요
검정에 대한 정보를 검토하고 싶으시면 PDF의 '검정' 섹션에서 찾으실 수 있습니다
네 왜 첫 번째 덩어리가 여기 메모리 맵의 시작점에서 시작되지 않고 이런 패턴이
남는지 궁금하실 겁니다
엄밀히 말하면 그렇죠
멀록은 사용자 데이터보다 16바이트 먼저 청크를 시작해요
말록의 관점에서 보면 첫 번째 덩어리는 여기서 시작돼요
네 프로그램이 청크를 다룰 때 사용자 데이터에 포인터를
주지만 맬록이 청크를 잡으면 16바이트 낮은 주소로 바뀌죠 ?
혼란을 더하기 위해 말락 덩어리는 적어도 이렇게 보면 변동성이 있고 몇 가지
요인에 의존합니다 이 덩어리의 크기와 앞의 덩어리의 크기 그리고 이
덩어리가 자유로운지 여부죠 ?
고기는 나중에 먹을게요
다행히도 처음 두 가지 기술로는 이런 모양의 덩어리를 볼 수 있을 겁니다
마지막으로 맨 위 칸이라고 불리는 부분을 주목해 주세요
네 기억하실 겁니다 아까 'vmmap' 커맨드 결과에서 이 힙은 13만 바이트
길이라는 것을요
하지만 여기서는 기껏해야 200 바이트밖에 안 보이죠
말록은 아직 사용하지 않은 기억을 맨 위 기억 조각으로 치부합니다
상단이죠 상단이라고 부르죠 하단에서 높은 주소로 메모리를 볼 때 하단처럼
보이긴 하지만요 안 그래요?
가장 높은 곳에 거주하는 지역 중 하나죠
네 말록에게 더미 기억을 요청할 때마다 말록이 이 위쪽 덩어리를
쪼개서 크기 필드를 주고 사용자 데이터를 알려 줬어요 안 돼요
맞아요 이렇게 계속 요청하면 말록이 맨 위부터 계속 가져가겠죠 메모리가
부족해지면 요청을 들어줄 수 없을 거예요
그러면 말록은 위쪽을 늘리려 할 겁니다
그리고 요청을 수행할 만큼 큰지 확인하기 위해 크기 필드도
얻습니다 여기서 볼 수 있죠
그리고 흥미롭게도 글립벡의 많은 버전에서 큰 덩어리만 한 밭은 건전성을 검사하지
않습니다 이것이
힘의 의회의 기반이 되죠 ?
당신은 "그만" 명령이나 컨트롤+d로 GDB를 닫을 수 있습니다.
다음 영상에서는 취약한 첫 쌍성을 살펴보고 지금까지 알아낸 것을 활용해
어떻게 활용할지 보겠습니다