*IDA 기준으로 함수 이름 작성
* 메뉴1: sub_400DF8 함수 : malloc 함수
- 전역변수 buf, qword_6030f0, qword_603100, qword_6030e0, qword_603108, qword_6030e8 : heap 메모리 주소 저장하는 전역변수
- 전역변수 dword_603120, dword_603114, dword_603124, dword_603118, dword_603128, dword_60311c : 사용 상태 체크 변수
* 메뉴2 : sub_40120C 함수 : free 함수
* 메뉴3 : sub_4013E0 함수 : edit 함수 -> overwrite
전역변수에 heap 메모리 주소 저장한다. -> unsafe unlink 사용 가능
unk_603110 변수 크기는 4바이트인데 5바이트 입력 가능 -> 1 byte overflow
unk_603110+4, 즉 dword_603114 전역변수의 1바이트를 컨트롤 가능
이 변수는 2번에서 calloc 시 사용 상태인지 상태 체크하는 변수이다.
따라서 2번 free 후에 이 체크 비트가 0이 되서 2번 메뉴에서 if문에 의해 double free가 불가능한데,
unk_603110에서 1로 만들어서 2번이 사용상태인 것처럼 만들고 다시 free를 하면 double free가 가능하다.
1번 메뉴에서 qword_603130 변수의 상태를 체크하는 if문에 의해 malloc은 3번까지 가능하다.
하지만 sleepyholder에서 fastchunk 1개와 largechunk 2개 할당으로 fastbin_dup_consolidate를 하고 unsafe_unlink를 이용해서 exploit했기 때문에 3번의 malloc은 충분하다.
2번으로 할당할 때만 체크 변수 값을 변조해서 double free가 가능하므로 2번을 fastbin으로 하고 unsafe unlink의 fd와 bk에서 기준이 되는 전역변수 주소도 2번의 heap 주소 저장하는 전역변수로 한다.
unsafe unlink를 사용해서 할당 주소 영역을 원하는 전역변수 영역으로 바꾼다.
# process
1. fastbin_dup_consolidate
fastchunk 할당
2번째 chunk 할당 (fastChunk를 largeChunk와 인접하지 않은 상태로 만듬)
fastChunk 해제
largeChunk 할당
fastChunk 해제 : largeChunk와 인접하지 않은 경우 fastChunk는 smallbin에 들어간다 => fastbin_dup_consolidate
- 이때 DFB를 위해 1번째 chunk의 사용 상태 변수를 1로 만들어야 한다.
=> 1byte overflow 이용해 이 사용 상태 변수 값을 1로 만든다.
2. unsafe unlink
2번 chunk를 생성하고(fastbin)
3번 메뉴에서 edit을 할 때 2번 청크에 fake chunk를 생성한다. (unlink() 과정 시 체크 사항 우회하기 위해)
=> prev_size = 0x0, size = 0x0, fd = &qword_6030F0-0x18, bk = &qword_6030F0 – 0x10
=> 이때 nextChunk의 prev_size를 0x20(prev_inuse비트 해제된 상태로) 으로 줘서 fakeChunk가 이전 청크인 것처럼 한다.
fakeChunk를 생성하고 4번 chunk를 해제(free)한다.
4번을 해제하면 unlink 매크로에 의해 다음 calloc이 할당되는 주소가 &qword_6030F0-0x18이 된다.
이제 libc leak을 할 수 있다.
3. libc leak
Unsafe_unlink 후 &전역변수-0x18 위치에 있다.
따라서 3번 메뉴에서 edit 시 1번 청크에서 data를 줄 때 0x6030d8 주소부터 받으므로 이 값은 0으로 주고(사용하지 않으므로) 0x6030e0 주소 값에는 free@got를 넣는다.
그리고 2번째 청크 edit 시 puts@plt를 줘서 free@got에 puts@plt를 적는다.
그럼 free(read_plt) 시 인자를 libc 주소로 주면 libc 주소를 leak할 수 있다.
libcBase를 구할 수 있고 system, binsh addr를 구할 수 있다.
4. system(“/bin/sh”) 실행
free@got를 system@plt로 덮는다.
그리고 heap 주소 값 저장하는 전역변수 값을 "/bin/sh" 값으로 변조하고 free하면 system("/bin/sh")를 실행할 수 있다.
# exploit code
# exploit
[Def Camp 2016] Warm Heap (0) | 2020.01.22 |
---|---|
[HITCON-Training] lab14 : magicheap (0) | 2020.01.12 |
[HITCON 2016] SleepyHolder (0) | 2020.01.08 |
[HITCON-Training] craxme (0) | 2020.01.02 |
[HITCON-Training] crack (0) | 2020.01.02 |