네 이 영상에서는 부식의 집을 살펴보겠습니다 기존의 개발 기법에서 착안한
세 가지 원시적인 건물입니다 네 원시적인 3은 좀 이상하지만 착취 개발
중에 뭐가 유용할지 모르죠 ,
네 첫 번째 비 새는 기술입니다 이걸 조개껍데기로 활용하는 방법을 보여드리죠
부식 디렉터리를 검색해서 취약한
바이너리를 살펴보죠
확인 확인 섹션은 대부분의 Linux를 실행하고 해킹 완화와 글립벡 버전 2에 링크돼
있습니다 정확히는 27개죠
우분투 18호를 탑재한 우주선요 4년 곧 보시겠지만 글립코 제품 쌍성에는
단점이 있어요
하지만 이 기술이 실전에 통한다는 걸 증명하고 싶어요
GDB를 통해 부식 이진법을 실행해보죠
도청기를 찾고 싶으면 지금 당장 영상을 멈춰서 찾아요
네 덩어리를 많이 요청할 수 있어요 우리 기준으로는요 옵션 1로 하죠 0x3b00
이하 크기로 제한됩니다 ?
옵션 2는 인덱스로 덩어리들을 자유롭게 합니다
여기 온 김에 무균 벌레를 확인하죠
그런 행운은 없어요
옵션 3은 데이터를 덩어리에 쓰는 겁니다
10바이트 이상 쓰면 안 돼요
이미 비어 있는 0을 편집해서 그 후의 버그를 확인해보죠
프로그램은 불평하지 않습니다 더미를 검사해 보니 10바이트짜리 글이 무료로 남아 있습니다
네 우리 데이터는 0x20 tcachbin 포워드 포인터에 다음 사둔자를 두 바이트나 때렸습니다
버그는 10바이트 사용 후 사용되지 않습니다 사용자 데이터의 첫 4음절에서 시작하죠
이 벌레는 그 자체로 아주 강력해요
네 전에 작은 오버플로우를 이용한 적이 있어요 tcache가 개입하면 특히 더 강력해지죠
그럼 그냥 고리를 낚아채서 끝내면 안 되나요?
프로그램을 다시 시작하면 우리 주소는 안 새겠죠
네 지금까지 손상된 데이터를 판독해서 유출을 조작해 왔지만 이 프로그램에는
읽기 옵션이 없습니다 ? 읽기 옵션?
네 게다가 위치 독립성이 있는 2진법이라 ASLR의 명령을 따라야 해요 인폴리크 초기
화폐를 위조하기가 무척 어렵죠
아직 할 수 있어요 다른 기술로 배워보죠
하지만 지금은 그걸 모른 채 계속해야 해요
좋아요 이 프로그램이 결과물이 전혀 없는 것처럼 취약점을 개발할 거예요 메뉴는
디버깅과 실험을 쉽게 하기 위한 거예요
네 부식의 집에 대해 더 알게 되면 이해가 더 잘될 거예요 그럼
시작하죠
주소를 유출할 수 없어서 곤란합니다
네 그게... 가짜 덩어리 주소도 모르면서 인터넷이나 패스트빈 링크 리스트를 조작하면 무슨
소용이죠?
이 부분에서 비공식 버그가 중요합니다
이진법으로 실험을 해 보셨다면 데이터를 덩어리로 쓸
때 사용자의 바이트수만 쓴다는 걸 아실 겁니다
맞습니다 당연한 얘기지만 input을 10 바이트로 늦추는 건 아주 쉽습니다 예를 들어
input을 5 바이트로 한다면요
네 우리가 통제하니까 인라인 맬록
메타데이터를 부분적으로 덮어쓸 수 있어요
요청하고, 무슨 뜻인지 보여드리기 위해 덩어리 몇 개를 자유롭게 하죠
이 티캐빈 포워드 포인터의 가장 낮은 바이트 값을 보세요
네 버그를 이용해서 fd에 바이트 하나를 쓸 거예요 뉴라인 문자 없이 컨트롤
+ d를 이용해 입력을 종료하는 거죠
나중에 분석해 보니 포인터의 사소한 바이트만 덧입혀져 있었어요
부분 오버라이드는 매우 강력할 수 있어요 ASLR의 효율성이 많이 감소하니까요 네 이 경우 0x30 바이트로 표시된
제 아스키 0이 태체빈 fd를 가리키던 부분에서 tcache로
유도했습니다 ? 네
이걸 이용해서 구멍을 뚫을 수 있어요 구멍을 뚫는 거죠
그렇군요 물론 아직까진 한계가 있어요
생산 이진법이라면 유용하겠지만 중요한 데이터를 저장하지 않아서 좀 더 멀리
나가 보려고요
여러분 경기장 주소를 적는 좋은 방법은 두 개의 연결 목록에 일부를
빼내는 겁니다 무체중 목록 스몰빈, 라지빈
네 0x90이나 더 큰 치카빈을 채우면 돼요 더 쉽게 치카시 범위에서 0x420
이상 벗어나면 되죠
프로그램을 다시 돌려서 한 덩어리를 빼낼게요
경기장 주소를 적어뒀어요
아직 유출은 못 하지만 사후 작성 방지 버그를 써서 조작할 순 있어요
그럼 이미 배운 기술을 이용할 수 있을 겁니다 구전 기술이나
무체중 공격 같은 거요
지금까지 생각해둔 아이디어를 시험해보고 싶다면 지금 비디오를 멈추고 해보시기
바랍니다
네 실험이 끝나면 많은 기술의 전제 조건이 유출되지 않고는 만족시키기
어렵다는 게 명백해질 겁니다
그리고 한 덩어리에 10바이트까지만 쓸 수 있어서
fd나 가장 낮은 bk만 쓸 수 있어요
네 이런 상황에서는 체계적이지 않은 공격이 필수 조건의 기술로 눈에 띕니다 ?
맞아요 네 , 그러면
네 힙랩 1편에서 오렌지 하우스에서 파일 스트림 착취로 껍데기를 얻었을
때 무체중 공격의 위력을 목격했습니다 잠재력이
있어요
맞아요 그 수법을 재현하지 못하는 이유는 libc 정보 유출과 가짜 고객
명단이 필요했기 때문이죠
이 영화는 둘 다 없어요
네 하지만 방금 제가 시연한 부분 덮어쓰기 기술을 사용해서 혼란스러운 공격으로
근처 데이터를 겨냥할 수 있어요
무슨 뜻인지 보여드리죠
아 타깃 처리 과정이 aslr의 관리 대상이라 우체국 주소도 모르는 판에
정리가 안 돼 있습니다
꼭 그런 건 아니에요
네 x64와 Linux를 리눅스 낮은 주소 범위의 최상단입니다
1부에서 오렌지 하우스 개발을 하면서 배운 거죠
거나요
네 0x7f 대신 0x7e가 보일 때도 있고
메모리 압력이 이 값에 더 영향을 줄 수도 있지만
대개는 라이브러리와 런타임 매핑에 대해 0x00007f 주소를 확실히 추정할 수 있습니다
네 x64 메모리 매핑은 페이지 수준 세분성이 있습니다 의미는 중요하지 않은 12비트의 주소도
상수가 된다는 거죠 지난 강의에서
이 점을 이용했죠 ,
이 미정렬 주소는 0xca0이에요
이 장면은 글립코와 좀 다릅니다
그러면 ASLR 엔트로피와 관련된 주소는 28개만 남아요 x64 네 부분 오버라이티로 다른
것에 영향을 주지 않고 최소 바이트의 주소를 조작할 수
있습니다
네 정리가 안 된 bk를 덮어쓰면 정리가 안 된 bk를 공격할
수 있어요 이 주소에서 저 주소로요 ASLR 비트를 추측할 필요 없이요
네 타깃 프로그램은 싱글 스레드라서 우리가 건드린 건 libc
바이너리 데이터 섹션에 있는 주요 영역이에요
아레나 메타데이터뿐 아니라 libc 데이터도 공격할 수 있어요
다중 스레드 프로그램이고 우리 스레드가 메인 아레나를 공유하지 않으면 그때까지 새
스레드를 시작할 수 있어요
우리가 얼마나 통제했느냐에 달렸죠
안타깝게도 이 반경 내에 목표물이 없습니다
네 맨 위 포인터를 무정부 주소로 덧쓰고 경기장에 할당한다고 해도
다시 원점이에요 쓸 만한 주소를 못 쓰니까요 아직 유출된 게 없잖아요
우리가 덜 중요한 바이트 2개의 정돈되지 않은 bk를 덮어쓸 의향이 있다면 4비트나 ASLR
엔트로피가 나쁨을 예상할 수 있고 정돈되지 않은 공격 범위를 엄청나게 늘릴 수 있어요 글리벡 타겟을
더 포함해서요 제 _IO_list_all처럼요 예를 들면요
네 물론 물론 불가능하다는 걸 이미 확인했습니다 두 군데에서
정보가 새야 하니까요
그렇다고 해서 다른 좋은 목표물이 없는 건 아니죠
네 어떤 글립벡 변수가 혼란스러운 공격에 노출될지 알아보기 위해 2005년으로
거슬러 올라갈 겁니다 말록말레피카룸이 출판된 때죠
네 네 힘의 집 구전, 영혼의 집이죠
,
이제 프라임 하우스를 살펴보죠
이렇게 됩니다
버그를 활용해서 최소 크기의 값을 설정합니다 , 버그 크기로 설정합니다
네 그 덩어리를 빼내면 존재하지 않는 패스트빈에 연결될 거예요 슬롯 1개를 빼서 그 장소에 맞는
주소를 적을게요 안 돼요
패스트빈스 마이너스 1의 값은 같은 아레나의 일부이고 max_ast라는 변수를 가지고 있습니다
맥스_패스트는 패스트빈에 안전하게 연결할 수 있는 덩어리의 최대 크기를 정합니다
기본 조건상 경기장에 패스트빈 자리가 10개 있어요
네 하지만 맥스_패스트 변수를 프라임 하우스를 통해 힙 주소로 덮어쓰면 존재하지
않는 패스트빈에 덩어리를 연결할 수 있어요 지수는 10보다 훨씬 높고요
이렇게 프라임 하우스는 다음과 같은 원시 원리를 제공합니다 패스트빈스의 변수에 힙 주소를
입력하는 거죠 아레나 메타데이터도 포함해서요
네 메인 아레나를 사용하기 때문에 libc 메타데이터도 포함됩니다 stdio 파일 스트림
같은 거요
네 앞서 했던 이론적 무체계빈 공격과 별반 다르지 않아요 다만
이번엔 무체계빈 주소 대신 힙 주소를 쓰고 범위는 잠재적으로 훨씬
넓죠
네 안타깝게도 안타깝게도
, 하지만...
2006년 글립코 2편에서는 4는 네 max_ Fast 변수가
아레나에서 글로벌 변수로 옮겨져 global_max_
Fast라는 적절한 이름이 붙었다 맞아요,
2005년에 사용된 폐기된 기술이 2019년의 녹슨 집과 무슨 관계가 있을까요?
그게... 알고 보니 프라임 가문을 소생시킬 수 있더군요 글로벌_맥스_빠른 변수에
무체중 공격으로요
거기서 새로운 원시적인 요소를 끌어와 포탄을 투하할 수도 있죠
네 부식이 있는 집은 다룰 게 많기 때문에 한 단계씩 진행할 겁니다 폰툴스 템플릿 스크립트
안에 베어링을 넣는 것부터요
첫 번째로 libc 개체가 1, 2부에서 했던 방법과 약간 다르게 초기화된
게 보이실 겁니다
네 공유 개체를 구문 분석하는 대신 a 내의 분리된 바이너리 정보를
읽을 거예요 프로그램의 실행 경로에
있는 디버그 디렉터리를 살펴봅니다 네 네 이건 분리된 디버깅 기호 바이너리로 pwndbg 힙 인트로스펙션
커맨드에 필요한 메인_arena 같은 기호에 대한 정보를 갖고
있습니다
네 이런 디버깅 기호는 보통 프로덕션 libc 바이너리에 포함되지 않죠 공간을 너무 많이
차지하거든요
디버깅을 더 편리하게 하기 위해 이 과정을 위해 만든 라이브러리에 포함합니다
차이점은 다른 사용되는
디버그 빌드와 이 프로그램이 사용하는 프로덕션 libc의 크기를 비교해보면 아주 다양합니다
그건 파트 2에서 제가 맡은 libc 셸 기능이에요
그때 여러분 환경에 추가하지 않았다면 지금은 PDF에 있죠
일부 분산은 패키지 관리자를 통해 분리된 기호를 제공합니다
예를 들어, 우분토는 libc6-dbg라는 패키지를 통해 사용 가능하죠
모든 디스크로에 이 마인드가 있는 건 아닙니다 아치 Linux 같은 경우 동등한 패키지를 제공하지 않죠
네 디버깅 기호가 분리되어 있어서 조금 전에 이 프로그램을 검사할
수 있었습니다
그게 없으면 디버깅이 훨씬 더 힘들어져요
GDB는 기호 파일을 자동으로 감지합니다. 녹화할 때는 pwntools는 그렇지 않습니다.
그래서 수동으로 주입해야 해요
이건 해킹이에요 체세크는 등호죠 거짓 인수는 예외를 피하기 위해 요구됩니다
하지만 대안으로 위치 추적 기호를 손으로 그리면 시간이 훨씬 많이 듭니다
네 GDB 지침도 길어요 디버그를 하면서 glibc 빌드의 소스 코드를
볼 수 있어요
늘 그렇듯 스크립트는 프로그램 메뉴 옵션에 대한 포장 기능을 제공합니다 맬록, 무료,
편집
네 또 malloc_chunksize 함수도 있습니다 특정 크기의 덩어리를
직접 요청할 수 있죠
꼭 쓸 필요는 없지만 대본을 더 잘 읽게 해주죠
마지막 기능은 gmf_chunkize와 gmf_malloc입니다
네 대본 하단에 부분적인 덮어쓰기를 이용해 혼란스러운
공격을 할 수 있는 예가 있어요 네 네 단단한 몸통을
보호하는 겁니다 안 돼요! 큰 덩어리를
분리해서
빈 곳에 넣어요
다음 줄은... 복잡해 보이지만 애프터 쓰기 버그를 이용해서 가장 덜 중요한 두
바이트를 지운 거예요 맞아요, 정리가 안 된 청크 bk요
먼저 fd가 null이 됩니다 폰툴의 p16 함수는 bk 위에 두 바이트를 씁니다
이 프로그램은 10바이트까지만 쓸 수 있어요
이게 제한이에요
어수선한 공격의 목표는 아까 말씀드린 글로벌_맥스_패스트 변수입니다
네 바이트가 가장 작은 기호만 빼고 모든 걸 마스킹해서 준비합니다
물론 기호의 주소를 알 순 없죠 메모리
콜에서 바이너리에 매핑된 곳을 명시적으로 알려주지 않으면요 간단히 기호의
오프셋을 바이너리 처음부터 리턴합니다
하지만 이 정보는 아직 쓸 수 있어요
좋아요 네 메인 경기장의 무정리 쓰레기통 주소예요 ? 고정된
부분이 있죠
목표물인 global_max_ft의 주소도 같은 고정 비트를 공유합니다
게다가 이 주소들 사이의 거리는 고정돼 있어요
글로벌_맥스_패스트 글로벌_맥스_패스트는 두 페이지만 표시돼 있어요 이번 글립코
제작에서는요
즉 바이트가 가장 작은 주소 하나를 덮어쓰고 ASLR 엔트로피를 한 조각만
제대로 추측하면 다른 주소로 변환할 수 있다는 거죠
예를 들어 엔트로피 나블이 미체르드빈 주소에서 6이라면 max_ast 주소는
8이겠죠
우리가 이걸 직접 하는 대신 폰툴이 처리할 거예요 libc 로드 주소에
있는 ASLR 니블을 추측하면요
숫자 7은 특별할 게 없지만 3, 4는 피해야 합니다 그건... libc 이진이 aslr
엔트로피의 덜 중요한 곳에 3, 4가 있는 주소로 가면 무체계화된
빈 공격은 성공 못 해요
맞아요 무체중 빈이 주소로 뜨는 이유는 나블의 e나 f
때문이에요 추측하는 거예요 네 네 이 값에 두 개를 더하면 주소가 더 많이 손상되는데
우린 추측하지 않고는 조작할 수 없어요 8개의 ASLR 엔트로피요
템플릿 스크립트를 실행하면 예제가 보일 겁니다 GDB와 NOASLR 옵션과 함께요
절차가 끝나길 기다려요
libc 부하 주소를 확인해요
끝은 0x4000입니다 '불운한' libc 화물 주소죠
그 결과 무체중 빈이 0xfca0으로 끝나는 주소에서 발견되죠 네 기억하세요 무체중 빈은 덩어리로 취급되므로
엄밀히 말하면 경기장 맨 위에서 시작합니다 포인터 ?
네 네 , 0xdd
그래서 방향 감각을 잃은 공격은 빗나갔고 그래서 세그폴트를 썼죠 네 자료 화면이 혼란스러운 공격이 일어난
순간을 보여줍니다 부패한 bk가 우리를 따라왔고 목적지인 fd
위에 주소도 적혀 있습니다
손상된 bk의 지도를 확인하니 비쓰기 가능한 기억으로 향합니다 주소 끝부분에 0xdc1930이
아니라 0xdd1930이라고
적혀 있어야 해요
문제가 안 됐던 건 ASLR이 정지할 때마다 GDB가 이 주소를
선택해 우리가 해킹을 해제했다는 거예요
이 정도로 지체되진 않을 거예요
네 그 말은 해킹을 디버깅하는 동안 16번 중 2번은
실패한다는 거죠 ASLR이 "불운한" libc 로드 주소를 선택할 때요
대안이 있긴 해요
제한된 VA 공간 풍수를 실행할 수 있어요
네 LD_PRELOAD로 공간을 제한함으로써 가능한 공간을 제한할 수 있습니다
안타깝게도 이중성에서 안 되는 해결책도 있어요
일부는 libc 부하 주소를 극단적으로 바꾸는데 전부 이 지역에서만 구할 수 있어요
여기 하이랩랩에서는 최대한 어려운 일을 하려고 합니다
원격으로 공격하듯이 계속 진행하겠습니다
편집자 앞으로 돌아가세요
이 템플릿 스크립트를 다시 실행하겠습니다 이번에는 NOASLR 옵션 없이요
보통 16분의 1 확률로만 해킹을 오류로 바꿀 수 있어요 덜 중요한
asr 나블은 맞혔고 비효율적이죠
이 줄은 값을 정확히 추측해 디버깅하면서 속임수를 쓰게 도와줘요
네 나쁜 libc 부하 주소는 여전히 손쓸 수 없지만 그래도 세그폴트 프로세스가
다시 시도해요
GDB 옵션으로 스크립트를 실행합니다
vmmap libc-를 입력하세요 아니면 lm libc-
네 리bc 화물 주소는 저랑 다르겠지만 세그폴트가 안 떴다면 0x3000이나
0x4000이 아닐 거예요
네 네 무체포된 주소와 global_max_ fast 사이의 주소 차이가 다른
걸 알 수 있어요 나쁜 libc 부하 주소에서요 이 주소 간은 같아요
네 네 global_max_ast 주소로
변환할 수 있어요
우리 대본이 바로 그렇게 했죠
네 사후 작성 버그를 활용해 정돈 안 된 bk를 부분적으로 덮어써 global_max_ Fast
주소 마이너스 16으로 전환했어요 그렇게 정돈 안 된 bk 공격을 공격하니까요
스크립트의 마지막 줄은 단순히 부패한 것을 할당하고 공격을 촉발시킵니다
네 네 128이나 0x80의 기본값이 언스테르드빈 주소로
바뀌었습니다
기억하세요 네 가장 큰 덩어리 크기로 해석됩니다
안 돼요 이 상태라면 말록이 큰 덩어리를 풀어 주면 패스트빈 삽입이 가능하다고 착각할 거예요 안 돼요
여기가 내가 말한 원시적인 프라임 하우스예요
원래 방법과 다르게 설정했을 뿐이죠
_int_프리 기능 내 패스트빈 기능 검사부터 시작합니다
네 디버깅에 대해 말씀드리자면 프로덕션 libc 바이너리요 예를 들어 _int_프리에서 브레이크 포인트를 설정하면
gdb 집합이 다중 브레이크 포인트를 갖는 걸 아실 겁니다
네 프로덕션 libc 바이너리는 최적화가 뛰어나기 때문에 컴파일러가 함수를
inline 함수로 변환해 호출의 오버헤드를 방지합니다
한 개의 브레이크포인트는 실제 _int_프리 기능입니다
다른 코드와 인라인이 됩니다 나머지는 같은 코드로 _libc_프리 혹은 _int_프리라는 다른 장소로 인라인이 됩니다
알고 있으면 개발에 꼭 필요한 건 아니지만 모르고 있으면 혼란스러울 수 있습니다 안 그래요?
어쨌든 패스트빈 자격을 되찾았어요
get_max_ft 기능은 단순히 global_max_ft를 반환합니다
얼핏 보면 우리 계획에 반하는 부분이 있는 것 같아요
하지만 이 코드는 마지막 바이너리에 없어요 빌드인_접촉불가능은 컴파일러에 대한 최적화
힌트예요
네 그다음에는 패스트빈을 통해 덩어리를 연결할 수 있습니다 패스트빈_인수
매크로에서 결정하죠 덩어리의 크기를 오른쪽으로 4조각 옮기고 2조각을 빼요
예를 들어 0x20 크기의 덩어리가 패스트빈 제로에 도달하는 걸 봤죠 2가 4비트를 빼면 2가 되고
2를 빼면 0이 됩니다
네 우리 스크립트에서 gmf_chunkize 함수는 global_max_ast찹size 본질적으로 이
연산의 반대의 일을 수행합니다 ???? 오류가 발생하면 주소를 전달하거나
더 정확히는 libc 바이너리 내의 오프셋을 전달할 수 있습니다 힙 주소로
위치를 덮어쓰려면 덩어리의 크기를 알려줍니다
작동하는지 보죠
편집장으로 돌아가시면 큰돈을 무료로 요청하겠습니다
잘 들어요 이 덩어리를 요청하면 이 대본이 끝날 때쯤 비체계성 빈을 자극해서
불안정하게 만들고 다음 요청에서 중단될 가능성이 커요 안 돼요
하지만 멀록은 무체계빈의 요청을 받지 않을 거예요 우리 패스트빈은 어떤 요청이든 받아
줄 수 있다고 생각하거든요 글로벌_맥스_빠른
부패 덕분이죠
이로 인해 말록은 패스트빈 슬롯인 줄 알고 배분하려 하지만 사실은 글립벡
데이터일 뿐이고 세그폴트나 중단으로 이어질 가능성이 큽니다
그래서 혼란스러운 공격을 촉발하기 전에 요청을 해야 합니다
윗부분을 강화 보호대로 감싸요
이 포인터를 노릴 거예요
네 제가 파일을 착취하는 건 주소를 유출할 수 없어서 안 된다고 했지만 그건
두고 봐야죠 지금은 그냥
맞춰줘요
네 스크립트 gmf_malloc helper 기능을 쓸 수 있어요 gmf_chunksize와멀록_chunksize를
감싸는 래퍼죠 특정 타깃을 손상시킬 적당한 크기를 요청하기 위해서요 , 주소만 알려주면 돼
네 네 오렌지 하우스에서 배운 거예요
?
행을 수정했다면 GDB 옵션으로 스크립트를 실행합니다
명심해요, 매크로에서 세그폴트를 만나면 libc 부하 주소를 확인하고 다시 시도해요
방향을 파악하게 좀 쉬세요
트럭은 이렇게 생겼습니다 트케이시와 상부 트렁크 사이에 덩어리가 두 개뿐이죠
첫 번째는 부패한 bk로 자유롭고 혼란스러운 공격입니다
글로벌_맥스_패스트변수 확인했는데 공격은 성공했습니다
네 두 번째 덩어리는 여전히 할당되어 있고 크기는 우리 스크립트에 있는 gmf_chunkize helper 함수에 의해
결정됩니다 ,
스티더 vtable 포인터를 목표로 하자고 했죠 패스트빈 슬롯은 하나의 기계 단어로 이 경우에는
8바이트 너비입니다
네 그래서 목표물과 겹치는 패스트빈 슬롯을 찾기 위해서 0과 패스트빈 사이의
거리를 계산하고 8로 나누면
됩니다
네 물론 패스트빈
0x161은 존재하지 않지만 글로벌_맥스_빠른 부패 덕분에 멀록은 있다고 생각하죠
이 덩어리의 크기를 계산하기 위해 풀어 주면 패스트빈 0x161에 연결됩니다
패스트빈_인덱스를 뒤집으면 돼요 2를 더하고 4를 좌회전시키는 거죠
두 번째 덩어리의 크기를 알 수 있죠
0x1630
gmf_malloc helper 기능이 자동화되는 전체 과정이에요
작동하는지 보죠
지금 우리의 목표물인 스트더의 조준점은 libc로 가는 방향을 가리킵니다 _IO_file_jump
table에요
이제 인덱스 1에서 큰 덩어리를 떼어내죠 네 네 패스트빈 삽입이 가능한지
확인하고 0x1630 패스트빈과 연결하려고
해요 스트더의 vtl 포인터와 겹치거든요
성공한 것 같네요
네 주소는 유출되지 않고 임의의 libc 지점으로 주소를 적어뒀어요
부식된 집의 첫 번째 원시적인 모습입니다
네 프라임 가문과 기본적으로 같은 결과지만 글로벌 맥스_패스트에 혼란스러운 블라인드 공격을
가하는 거죠
네 넘어가기 전에 _int_프리 소스 코드를 살펴봤다면 이 원시적인 코드를 완화할
수 있는 수표를 보셨을 겁니다 ?
네 패스트빈에 연결한 다음 쓰레기통 앞에 있던 덩어리를 오래된
것으로 분류하면 패스트빈 크기를 확인해야 합니다 ,
네 패스트빈 둡에서 우회하는 것과 같은 건데 말로크 대신 무료로 시행했어요
오래된 것의 크기와 패스트빈에 있는 덩어리의 크기를 비교하고 있습니다
네 이건 배수구예요 오래된 건 제대로 된 게 아니거든요 ? 오래된 건 가짜예요 대상 변수가
가졌던 값을 힙 주소로 오버 작성하기 전에 갖는 거죠
대상이 null이면 그걸 무시할 수 있는 걸 보실 수 있죠
그렇지 않으면 낙태나 세그폴팅이 될 가능성이 커요
아직 못 찾았어요 우리 공격은 성공했고 우리 표적인 스트더의 확실한 조준점은
그 전에 무효가 아니었습니다
해브 락 변수가 우리를 구해줬네요
이 확인은 인수인 _int_프리 인수가 0이 아닐 때만 실행됩니다
하지만 _libc_프리 는 항상 _int_프리 를 호출하고 have_lock 를 0으로 설정합니다
네 이 확인은 _int_프리 호출이 아레나를 먼저 잠그는 다른 함수인 realloc에서
실행되지 않는 한은 안 됩니다
그래서 초기 1호는 이 수표가 있는데도 작동하는군요
이 기술과 프라임 가의 차이점은 제2, 제3의 원시 기술이에요
말록의 내장을 살펴봤으니 아시겠죠
패스트빈에 덩어리 하나가 연결된 것뿐이에요
이 과정은 두 단계로 나뉩니다 방금
보신 두 번째 단계는 말록이 청크의 주소를 적절한 패스트빈 슬롯에
적는 겁니다
첫 번째 단계는 패스트빈 링크 리스트를 유지하는 겁니다 현재 타깃 패스트빈 자리를
차지하고 있는 리스트를 fd로 복사하는 거죠
verbose 깃발을 pwndbg의 힙 명령에 전달하면 확인할 수 있습니다
이 큰 덩어리의 fd는 스트더의 포인터와 원래 가격을 유지합니다
네 직접적인 도움은 안 돼요 이건 무료고 읽기 후 버그가 없거든요
하지만 쓰기 후 무첨가 버그가 있어 이 값을 조작할 수 있죠
네 4비트는 이미 추측했기 때문에 libc 로드 주소 엔트로피를 덜
중요한 두 바이트를 덮어쓸 수 있죠 다시 추측하지 않고요
물론 이 포인터를 손보고 그대로 두는 건 별 도움이 안 됩니다
네 네 패스트빈 크기 검사를 통과해야 해요
이때 부식의 원초적인 부분인 2번이 유용하게 쓰입니다
0x1630 크기의 덩어리를 분배하면 어떻게 될까요?
그렇군요 말록은 우리 요청을 패스트빈 범위 내로 고려해서 존재하지 않는 패스트빈
슬롯으로 배당하려고 할 거예요 스타더의 포인터를 손상시켰어
그 칸은 0x1630번의 주소가 들어 있어요
초기화 작업 결과죠
이 덩어리를 할당하면 원시적인 건 반대가 돼요
네 청크의 fd를 0x1630 패스트빈 슬롯에 복사해서 포인터를 복원하고 저희가
개조한 부분을 포함해서 원래 위치로 돌려놓을 겁니다
이렇게 하면 원시적인 두 개가 원시적인 한 개로 만들어져서 libc 데이터를 임의로 조작할 수 있죠
대본으로 돌아가서 직접 해 보죠
0x1630 사이즈 청크로 시작하세요 전 그냥 라지_청크라고 하죠
이걸 빼내야 해요 방금 수동으로 뺐거든요
원시적인 방법이 나옵니다 스트더의 포인터에 주소를 적고 원래 가격을
그대로 옮기는 거죠
이제 포인터를 조작할 수 있어요
네 위치를 정할게요 _IO_str_jump라는 테이블 근처를 가리키면 됩니다 _IO_file_jump가
아니라요
그 중요성은 나중에 나오죠
네 혼란스러운 공격처럼 And 마스크를 이용해서 가장 낮은 바이트의 주소만 적습니다
네 마지막으로 마지막으로 안
그러면
GDB 옵션으로 스크립트를 실행하세요 안정될 때까지요
잠시 후 달 착륙정 사령부에 지시해서 스트더의 조준점이 지금 어디 있는지 확인합니다
_io_file_ 점프입니다 예상대로 가장 가까운 기호는 _IO_str_jump입니다 확인하자면 _IO_file_
점프입니다 stdout과 stdin 파일 스트림에 동일한
명령을 발령합니다 ,
부식의 집 2 libc 변수 수정하기
아직 배울 게 많으니
지금까지 다룬 걸 간략히 검토해보죠
프림티브 1은 현대적인 프라임 하우스입니다 네 큰 덩어리를 풀면 민감한 글립코드
데이터 위에 힙 주소를 적게 됩니다 우리 아레나가 메인 아레나입니다
원시적인 방법의 부작용은 목표 글립코 변수가 적혀 있다는 거죠 네 Primive 2는 이를 이용합니다
힙에 있는 동안 global_max_ Fast을 부분 혹은 완전히 덮어쓰기 위해
사용했던 버그를 그대로 활용하는 거죠
네 이렇게 해서 초기 복제품에 사용된 글립코 변수를 원래 위치로 돌려놓습니다
안 돼! 안 돼!
이 두 미개한 동물은 혼자 힘으로도 아주 강해서 말똥가리 몇 마리만
있으면 공격할 수 있습니다 이런 프로그램에서 libc 주소를 빼돌릴 수도 있어요
그럼 읽을 수가 없죠
그건 나중에 방법을 배우겠지만 지금은 이 프로그램을 유출할 수 없는 것처럼 다뤄야
해요
네 이제 Primive 3입니다 가장 강력하지만 복잡하기도 하죠 그래서 별도의
비디오를 예약했어요 다음 단계로 넘어가기 전에 1번과
2번부터 익숙한지 확인하세요
필요하다면 pwntools 스크립트 예제를 강의 리소스에 준비해 뒀습니다
다음 영상에서 만나요