일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- extends
- 회피
- opcode
- 버킷리스트
- Recylcer
- 여행계획
- 치유
- 일상회피
- Navigation Component
- 보안
- Android
- throws
- bytecode
- static
- abstract
- ㅇ
- Shared Elements
- jvm
- IMPLEMENT
- HelloWorld
- 보안취약점
- javap
- 심리여행
- Interface
- bytecode 분석
- 일상탈출
- Transition
- 취약점
- 심리학
- 여행
- Today
- Total
패스트터틀
보안 취약점(19.5.29) 본문
Heap Tyeps
signature : 0xeeffeeff 를 만나면 heap라는걸 알수있음
Segment : 받아온 덩어리
Heapalloc(0x1000 = req_size)
실제 allocsize = req_size + 8(information about heap = header)
HEAP영역에 대한 공부가 더 필요하다고 느낀다. 잘 이해가 안간다.
Low Fragmentation Heap
LFH of Allocation은 Heap안에서 메모리가 17번째번 할당되면 활성화되는것
0x100 = 256
+
8
-----------------
264
는
Bucket표상 33번째에 해당하니 33번째를 쓴다.
(Bucket은 16384 보다 작은 사이즈만 허용)
해당 Bucket은 SegmentInfo '
(virutal alloc은 kernel에게 필요한만큼만 받아와야되서)
heap 많이 받아와서 쪼개서 씀
LFH heap은 0x100(256)짜리가 17번 생성되면(이론이 적용된것같음) 0x100짜리를 30개 받을수있는것들을 미리 생성함
(미리 쪼개버리자)
그리고 이제 0x100이 할당이 되면 여기다가 넣어버림 => 이러면 안쓰는공간이 최소화됨,또한 매우빠르게 연산가능
그리고 만약에 0x200을 할당을 받으면 이것도 또 17개가 되면은 또 크게 받아서 쓰이도록 되어있음
0x100일경우 0x2000만큼 받음(
다시한번 정리하면 heap이 virtual alloc에서 받아오는거를 segments 그리고 sub-sugments로 나누고
그러면 sub-subments는 어떻게 크기를 결정하냐면 0x400, 0x800, 0x,1000 ~~~ 0x40000
이러한 표가있는데
Buckets(0x100,0x200....) - Size of UserBlocks(0x400,0x800...)
0x2000 - 8(info) /(나누기) 0x100 + 8(info) = 30버켓
근데 0x100을 계속 무한대로 받아오면은 0x2000 17번주고 그다음에 0x4000을 8번주고 한다. 0x8000 bytes 8번받아옴
Bucket -> segments -> activesubsegment -> usersub -> aggregateExchg -> FreeEntryOffset = 0x2
Offset은 0x2 x(곱하기) 8 = 16 = 0x10bytes (그다음번이 어디냐고 알려주는거)
(single linked list처럼)
이런식으로 따지면 복잡도(엔트로피?) 가 1로 굉장히 단순해져서 빨라진다는것임
Last Free First Use 라는 특성 ( window 7까지만 )
이렇게 해서 쭈우구~~~~~~~~~~~~~~~~ 40000까지 채우면 다 채워버리면
Virtual alloc에서 새롭게 받아옴 그리고나서부터는
0x100000, 0x200000, 0x400000,0x800000, 0xfd00000 ( windows 7 )
HeapManager는 브라우저나 프로그램마다 다 다르다.
해킹할때 이런게 필요하다는것도 알면좋지만 내가 만든 프로그램이 어떻게 메모리가 할당이 되고있구나 라는것을 알면은 좋음.
# Virtual Alloc 으로 받아지는 메모리 영역은 항상 0000으로 끝난다.
18개를 만든순간 frontend가 활성화가 되고 Localdate-0번째-seg정보-32번째를 보니
활성화가 되었으나 아무것도 안채워진 상태에서 데이터를 더 채워보면(100개정도)
이렇게 해서 LFH offset 만큼 subsegment에서 더하면 다음 free공간이라는것을 알수있음
어떤 특정 버켓의 LFH가 활성화가 되면 해당사이즈에 해당하는것은 LFH만 쓴다.(LFH아닌영역이 free가되어도)
Last Free first use는 맨마지막에 해당하는것만 딱 하나만 하고 나머지는 기존 활성화된 subsegment를 함
defualt heap
기본적으로보면 printf나 이런것들을 쓰면 여기다가 쓰기때문에 기본적으로 채워져있는걸알수있따.
LFH는 기본적으로 깨끗하다.
0045af98: 00060 . 00038 [101] - busy (2e)
0045afd0: 00038 . 01008 [101] - busy (1000)
0045bfd8: 01008 . 01008 [100] ---------여기서부터 데이터가 들어감
0045cfe0: 01008 . 00020 [111] - busy (1d)
데이터 집어넣고
0045af98: 00060 . 00038 [101] - busy (2e)
0045afd0: 00038 . 01008 [101] - busy (1000)
0045bfd8: 01008 . 00108 [101] - busy (100) ---------여기서부터 데이터가 들어감
ㅁ 0045c0e0: 00108 . 00108 [101] - busy (100)
ㅁ 0045c1e8: 00108 . 00108 [101] - busy (100)
ㅁ 0045c2f0: 00108 . 00108 [101] - busy (100)
ㅁ 0045c3f8: 00108 . 00108 [101] - busy (100)
ㅁ 0045c500: 00108 . 00108 [101] - busy (100)
ㅁ 0045c608: 00108 . 00108 [101] - busy (100)
0045c710: 00108 . 00030 [100]
ㅁ 0045c740: 00030 . 00108 [101] - busy (100)
ㅁ 0045c848: 00108 . 00108 [101] - busy (100)
ㅁ 0045c950: 00108 . 00108 [101] - busy (100)
ㅁ 0045ca58: 00108 . 00108 [101] - busy (100)
ㅁ 0045cb60: 00108 . 00108 [101] - busy (100)
ㅁ 0045cc68: 00108 . 00108 [101] - busy (100)
ㅁ 0045cd70: 00108 . 00108 [101] - busy (100)
ㅁ 0045ce78: 00108 . 00058 [101] - busy (4c)
ㅁ 0045ced0: 00058 . 00110 [101] - busy (100)
ㅁ 0045cfe0: 00110 . 00108 [101] - busy (100)
ㅁ 0045d0e8: 00108 . 00108 [101] - busy (100)
17개가 생성되고
여기다가 하나더 만들면
다시 하나 더만들면 30개의 LFH데이터가 생김
0045cfe0: 00110 . 00108 [101] - busy (100)
0045d0e8: 00108 . 00108 [101] - busy (100)
0045d1f0: 00108 . 02000 [101] - busy (1ff8) Internal
LFH data region at 0045d1f8 (subsegment 00457bd8):
0045d208: 00108 - busy (100)
0045d310: 00108 - free
0045d418: 00108 - free
0045d520: 00108 - free
0045d628: 00108 - free
0045d730: 00108 - free
0045d838: 00108 - free
0045d940: 00108 - free
0045da48: 00108 - free
0045db50: 00108 - free
0045dc58: 00108 - free
0045dd60: 00108 - free
0045de68: 00108 - free
0045df70: 00108 - free
0045e078: 00108 - free
0045e180: 00108 - free
0045e288: 00108 - free
0045e390: 00108 - free
0045e498: 00108 - free
0045e5a0: 00108 - free
0045e6a8: 00108 - free
0045e7b0: 00108 - free
0045e8b8: 00108 - free
0045e9c0: 00108 - free
0045eac8: 00108 - free
0045ebd0: 00108 - free
0045ecd8: 00108 - free
0045ede0: 00108 - free
0045eee8: 00108 - free
0045eff0: 00108 - free
그리고 여기다가 100개정두를 더 집어넣으면
00460498: 00108 - busy (100)
004605a0: 00108 - busy (100)
004606a8: 00108 - busy (100)
004607b0: 00108 - busy (100)
004608b8: 00108 - busy (100)
004609c0: 00108 - busy (100)
00460ac8: 00108 - busy (100)
00460bd0: 00108 - busy (100)
00460cd8: 00108 - busy (100)
00460de0: 00108 - busy (100)
00460ee8: 00108 - busy (100)
00460ff0: 00108 - busy (100)
004611f0: 02000 . 00180 [100]
00461370: 00180 . 02000 [101] - busy (1ff8) Internal
LFH data region at 00461378 (subsegment 00457c18):
00461388: 00108 - busy (100)
00461490: 00108 - busy (100)
00461598: 00108 - busy (100)
004616a0: 00108 - busy (100)
004617a8: 00108 - busy (100)
004618b0: 00108 - busy (100)
004619b8: 00108 - busy (100)
00461ac0: 00108 - busy (100)
00461bc8: 00108 - busy (100)
00461cd0: 00108 - busy (100)
00461dd8: 00108 - busy (100)
00461ee0: 00108 - busy (100)
00461fe8: 00108 - busy (100)
004620f0: 00108 - busy (100)
004621f8: 00108 - busy (100)
00462300: 00108 - busy (100)
00462408: 00108 - busy (100)
00462510: 00108 - busy (100)
00462618: 00108 - busy (100)
00462720: 00108 - busy (100)
00462828: 00108 - busy (100)
00462930: 00108 - busy (100)
00462a38: 00108 - busy (100)
00462b40: 00108 - free
00462c48: 00108 - free
00462d50: 00108 - free
00462e58: 00108 - free
00462f60: 00108 - free
00463068: 00108 - free
00463170: 00108 - free
쭈욱생성이된다.~~
넣고 뺏고 하는거는 기본적으로 global heap하고 똑같다.
객체 분석
classes(분류) - object(분류에 해당하는 예시)
class B1{
}
B1 *b1 = new B1();
void func <-> virutal void func() == virtual을 사용하면 func의 주소가 들어감
[ virtual void func() ] == [void *func = func()] 포인트가 들어가기 때문에
(포인터값을 포함하기때문에, 포인터가 같이 데이터입력되기때문에)
void main(){
Foo *f = new Foo();
f->foo();
}
==
IN ASSEMBLY
mov ecx, <addr. of the foo object>
call 0x4040404 == call func // addr of the foo's func() // 이런식으로 된다고보면됨
Struct Bar{
void *function_pointer;
unsigned int bar;
};
void main(){
Bar *b = new Bar();
b->func();
}
==
IN ASSEMBLY(x86)
mov ecx, <addr. of the foo object>
mov eax, [ecx+4];
call eax; // Indirect call 주소를 가져와서 eax넣는 과정을 거침 , 객체에서 이주소를 가져옴
call 0x4040404 == call func // addr of the foo's func() // 이런식으로 된다고보면됨
오브젝트의 할당 b1
malloc과 new는 = heapalloc을 -> default heap을쓴다.
free , delete는 -> heapfree을 <- Default Heap에서
B1 *b = new B1()
B1 *b = (B1*)HeapAlloc();
이렇게 똑같다는것인데 이것은 LFH에 할당이 된다.
그러면 왜 malloc으로 안쓰고 new b1이런식으로 쓰느냐라고 묻는다면
b->uint_in_b1 = 0; <<<<<<<< 이 기능을 쓸려면 생성자를 써야만 사용가능하다.
class B1{
unsigned int uint_int_b1;
B1(){
b1 = 0x41414141;
}
~B1(){
}
}
free(b) 라고 안하고 delete b; 라고 하는이유는 delete b 는 b->~B1(); 하고 free(b)해주는 역할을 동시에함
그렇기때문에 이런식으로 쓴다는 부분이다.
여하튼 new b를 하면 heapalloc(sizeof(b1)) 하고 같다라는 얘기이다.
여기 서브세그먼트를 들어가서
머라고 했는데 잘모르겠음 버킷이 이렇게 되어서 확인해보니 도표를 보니 저렇게 되었다고함
java의 경우에는
VM(Virutal Machine)이 있어서 java a.class 라고한다면
vm a.class(bytecodes) -> x86으로 파싱해서 변한다고 함
new A() 이 사이즈가 20이라고 칠때
VM이 -> 0x20 을 처리하기위한 버켓이 반드시 있음
LFH도 병행해서 사용하게된다. 자바에 관련된 것들은 Custom heap manager 그밖 c처리는 LFH Heap Manager가 처리한다.
https://github.com/jaeseolee/IS571-ACSP-Fall-2018/tree/master/lec04
8+8(헤더) = 16
17째에 LFH가 활성화되고 18번째부터 LFH에 들어감
다중상속
다중상속을 받으면 HEAP 에서 합쳐진다고 보면됨
virutal을 썻던이유는 오버라이드 기능을 쓸수있기때문이다.
int foo()
{
return 0;
}
int main(){
foo(); -> call foo
return 0;
}
virtual을 하지 않으면 f1을 호출할때 해당 클래스껏만 사용가능하고 밑에 오버라이드도 안됨
mov eax, [ecx];
move eax, [eax]
call eax; <-- 이게 상수값이기때문에 포인터로는 상속을 변경할수있기때문에 virtual을 쓴다.
Triple Inheritance
순서대로 b1 b2 b3 d 로 되어있는것은 형변환을 위해 table이 존재한다.
(casting 을위해서)
Up cast는 안전하다
Down cast는 작게 메모리 할당했는데 더많은 엑세스를 하니 위험하다.
Custom Heap Manager
윈도우는 자체 Heap이 있다.
근데 S/W는 따로 Heap을 만들어서 쓰기도함
왜냐면 플랫폼 통합(Linux,window,mac에서도 배포하고싶어서) 또는 최적화, 보안기능을 넣고싶어서
Flash Player
content created하는것, 4억개시스템에서 사용되다가 이제 사장될위기에 처함
flash는 dll아니면 activeX기능으로 동작함, offices도 flashdll chrome은 untrusted 권한으로 flash.dll을줌
Youtube swithches HTML5 video 이후로 줄어들고있다.
크롬에서 플래쉬를못쓰게 하는거는 보안상 그리고 느리고 전력사용이 많아서 모바일에 불리
(0day : 하나도 공개되지 않는, 1day : 공개는되었음 근데 모든 사용자가 패치를 하거나 보완한것은 아님)
p-zero 팀이라는곳에서 2015년에 300개이상의 취약점을 공개하면서 flash를 버리자라고함
Custom Heap Manager for Flash
GCAlloc GCLargeAlloc VirtualAlloc LargeAlloc FixedAlloc
GCBlock은 Userblock이랑 똑같음 GcHeap은 7b0 보다 큰얘들 관리 하는얘들 무조건 16M로 나눠서 할당
해서~~~ 문서참고해주세용^^
Chrome
왜 굳이 구글은 크롬브라우저를 만들었을까? 근데 결국은 크롬이 이겼음...
근데 사파리는 계속 올라가는게 앱등이들이 올려주는것이다.그리고 정책상 WebKit을 애플사꺼만 쓰게 해놓음
사실상 엔진은 전부다 chrome(naver,samsung internet등등)
크롬은 매우 안전한데 이유로서는 개발프로세스를 굉장히 잘만들었기때문에
크롬은 4가지로 버젼을 관리한다. canary(까나리젓갈 생각나는) 버젼 개발자들이 취약점을 공개해서 서로 고칠수있고 하는 약간 위키백과같은것들을 하는 버젼이고 이것들에서 조금더 나아간것이 dev버젼을 만들고 그리고 안정화시키고 그리고 beta버젼을 만들고 취약점을 마지막으로 찾고 마지막에 가서 stable버젼으로 공개
공개된것을 컴파일할려면 엉청난 cpu개수로도 엉청나게 걸릴만큼 오래걸린다. 그만큼 웹브라우저이상의 거대한 프로젝트라는것이다.
문서참고^^
Object Tracking in Flash
TAGED POINT = A라는 객체가 할당이 되면 (LFH힙을 보면 0 또는 8이다. Virtual 0000 이런식)
끝에 3비트는 TAg 정보를 같이 주는 포인트를 같이 추가한것
이렇게 하면 찾기가 힘들다고함 (심볼값을 찾기가)
flash는 3비트 크롬은 1비트.
'Cyber Security(undergraduate) > security vulnerability' 카테고리의 다른 글
보안취약점(19.5.29) (0) | 2019.05.30 |
---|---|
보안취약점 (19.5.28) (0) | 2019.05.28 |