좋아요 세 번째 기술로 넘어가죠
위험하게 연결을 끊는 겁니다 말록 내장을 더 많이 사용해야 해요
자 지금까지 0x80 이하에서 해방됐을 때 패스트빈에 들어갈
만큼 작은 덩어리가 어떻게 되는지를 봤습니다 네 네 , '정신 분산'
'위험한_언링크' 디렉터리를 검색하고 GDB에 '데모 바이너리'를 로드하세요
컨텍스트 출력을 소스 코드로 설정하고 메인()
함수에 중단점을 설정하고 프로그램을 실행합니다
네 말록에게 구덩이를 요청하면 어떻게
되는지 알죠? 'next 2'로 두 가지를 요청하고 'vis'로 연결해요 0x90 크기의
구덩이가 두 개예요 a와 b는 기본값 힙에 있습니다
네 전에는 패스트빈에 덩어리를 풀었을 때 주변 덩어리에 아무런 영향이 없었어요
? 네 꼭대기
옆에 있다고 해서 행동이 달라지진 않았다
하지만 두 번째 덩어리를 꺼내면 어떻게 되는지 보세요 패스트빈에 넣기엔 너무 크고
맨 위에 붙어 있죠
사라져요 네 맨 위에 있는 덩어리는 '정상'이라고 하는
패스트빈에 들어가기에 너무 커서 맨 위에 합체합니다 '상자'에 따르면 모든 상자가
비었습니다
'다음 2인조'는 B를 요청하고
0x20 크기의 덩어리를 보내주세요
잠시 후 다시 돌아오겠습니다
네 그동안 위쪽과 붙어 있지 않은 보통 송아지를 꺼내 볼게요
'next'를 쓰면 A를 공짜로 드립니다
'시각'을 보면 세 가지 변화가 일어났습니다
첫 번째는 다음 덩어리의 prev_inuse가
제거됐다는 겁니다 빠른 덩어리를 해방했을 때
일어나지 않은 일이죠
얼마나 중요한지는 곧 알게 되겠죠
두 번째 변화는 사용자 데이터의 마지막 4분의 1이 prev_size 필드로 용도 변경된
겁니다 보다시피 크기가 일치하죠 이 또한 패스트빈을
다룰 땐 일어나지 않았던 일입니다
네 네 a가 아니라 b라는 것을 나타냅니다 이것은 말록의
몸이 평생에 걸쳐 어떻게
형태를 바꿀 수 있는지 보여줍니다
마지막으로 A 덩어리는 정서가 불안정한 곳에 연결됐어요
네 여기에 주석이 달렸고 '정신없는 명령'의 출력을 보면 확인할 수 있습니다
정서가 혼란스러운 것도 공짜 목록에 있어요
패스트빈과 달리 경기장마다 방향 감각을 잃은 곳이 하나뿐이죠
두 개가 연결된 원형 목록에는 어떤 크기의 조각도 담을 수 있죠 네 이중으로 연결됐거든요 앞뒤로 다
사용되죠 fd와 bk 포인터도 각각 사용하고요
여길 보면 네 네, 맞아요
네 네 패스트빈과 비슷하죠 말록은 앞과 뒤에 있는 뿔을
가짜 뿔처럼 다뤄요 안쪽에 있는 뿔을
네 PDF 레이아웃 다이어그램에 '아레나 레이아웃'이 뜨는데 무체중
포인터 두 개가 맨 위에 떠요
16개 단위를 빼면 기억으로 알 수 있습니다
둘 다 A를 가리키고 있어요 유일하게 정리가 안 된 부분이죠 네 청크 A와 Bk는 둘 다 '청크'를
가리키는데 맨 위 청크 포인터에서 시작하죠
네 이래서 말록이 머리를 가짜로 취급하는 거예요 특별한 사례로
보지 않으려고요
이건 머리가 덩어리처럼 보이는 모습입니다 네 네 fd는
다음 칸을 가리키죠 그렇게
계속돼요 ? 네
마지막은 fd가 있어서 방향 감각을 잃은 사람의 머리를 가리키죠
마지막 덩어리도 앞부분과 이어지거나 하는 식으로요
방향 감각을 잃은 곳은 마지막 부분으로 향하고 원이 완성되죠
네 패스트빈처럼 새로 분리된 덩어리를 무체중 상태의 맨 위에 올립니다 반면에 패스트빈과
달리 무체중 상태의 맨 끝에서 덩어리가 할당되죠
할당량은 나중에 다룰
겁니다
네 하지만 빠르게 풀어줘도 주변은 영향을 받지 않죠 하지만 b를
풀어주면 어떻게 될까요? 이미 a 옆에 있는 '다음'과 함께요 '정처 없이'라는 명령은
다른 이야기를 들려줍니다
네
덩어리 A와 B는 같은 크기로 통합됐습니다 0x120이라는
크기의 두 덩어리를 합친 거죠
네 네 네, 맞아요 prev_size 필드는 이전 것은
0x120 바이트 길이고
새 것과 크기가 일치합니다
보세요 네 새로 생긴 더 큰 덩어리요
?
즉, 자유롭고 정상적인 덩어리가 결합되는 거죠
과정은 간단해 보이지만
말로크가 어떻게 해야 할지 생각해 보세요
네 무료로 제공하면 먼저 근처의 덩어리가 통합을 위한 것인지 확인해야 합니다 ? 네
prev_inuse 플래그를 이용합니다 말록은 풀려난 덩어리의 전 단계 깃발을 확인합니다
이전 단계가 비어 있는지 확인하기 위해서죠 그리고 다음 덩어리가 무료인지 확인하려면
두 덩어리로 앞을 봐야 합니다 크기 필드를 이용해 다음 덩어리 다음에 prev_inuse Flag를
확인합니다
네 네 이미 연결된 무료 목록에서 제거해야 합니다 ,
그렇지 않으면 다른 목록에 연결되거나
같은 목록에 두 번 연결될 수 있습니다
네 그럼 말록이 더 큰 청크가 차지한 공간을 모두 계산해서 거기에 맞게 크기와 프리v_size 필드를
설정해야 해요
마침내 새로운 덩어리가 무감각한 혈관과 연결됩니다
통합 과정에서 가장 흥미로운 건 링크 해제 부분입니다 목록에서 덩어리들이
제거되는 거죠
네 컴퓨터 공학을 전공하신 분들께 이건 기본적인 링크 목록이지만 그래도
설명할 가치가 있어요
네 링크 목록의 장점 중 하나는 해당 목록의 가운데에서 쉽게 항목을 제거할 수 있다는 겁니다
네 만약 패스트빈과 같이 링크된 목록의 중간에서 항목을 제거하려면 제거하려는
것보다 먼저 항목을 찾을 때까지 반복해야 합니다 그런 다음 항목을 건너뛰도록
포인터를 수정합니다
1,000번 물건을 제거하고 싶으면 피해자 전에 있던 물건을 찾기 전에
999개의 물건의 앞부분을 확인해야 해요
네 보통 크기로요 하지만 덩어리가 커지면 말록은 쉽게 한 덩어리를 제거할 수 있습니다
많은 덩어리 가운데에서요 이중 링크 목록에선 이건
쉬워요
정리가 안 된 상태에서 덩어리를 꺼내려면 덩어리를 잔뜩 넣어야 해요
네 피해자 뒤를 따라서 목록의 다음 부분까지 가서 그 부분을 희생자의
bk로 덧쓰는 거예요
피해자 청크는 목록에서 빠져 있어요
네 다음 다음은 피해자의 fd로 그 부분을 덮어쓰는
거예요 피해자 덩어리는 앞뒤 목록에서 연결이 끊겼어요
네 예전 글립벡 버전에선 이 연결 해제 과정이 매크로로 진행됐는데 fd와 bk 포인터에 진실성
검사를 안 했어요 그래서 '위험'
해제죠 "위험" 해제
네 네 원시적인 '반사'라는 글자가 남습니다
즉, 가해자는 두 주소를 선택해 서로 근처에 쓸 수 있고 그 반대도
마찬가지입니다 ,
자 그럼 이 기술이 좀 더 복잡한 현대 버전에 접근하기
전에 2000년에 가서 nx가 나오기 전에 원래 설계대로 언링크 기술을
활용해 보겠습니다