기본으로는 덤프 생성 기능이 꺼져있음.
[레지스트리 설정]
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps
-DumpType(REG_DWORD) : 1 : 미니덤프, 2 : 풀덤프
-(optional) DumpCount(REG_DWORD) - 폴더에 저자오디는 덤프파일의 최대개수
-(optional)DumpFolder(REG_EXPAND_SZ) - 덤프 저장경로(DEFAULT:%LOCALAPPDATA%\CrashDumps)
최신목록
2019년 7월 16일 화요일
2019년 5월 3일 금요일
[WINDBG]BUGCHECK 7F(kernel stack overflow)
BUGCHECK 7F
UNEXPECTED_KERNEL_MODE_TRAP(7F)
Arg1 : EXCEPTION_DOUBLE_FAULT
stack limit 보다 더 큰 주소로 콜스택이 진입하여서 BSOD 발생함.
kf나 !stackusage를 이용하여 스택 메모리를 많이 사용한 모듈을 찾아서 코드를 수정해주어야한다. 커널에서는 스레드당 할당된 스택메모리가 x86 : 12k, x64 : 24k 로 제한적인데 그 이상 사용시 BSOD가 발생한다.
KF 로 확인시 20D0의 스택메모리를 과다하게 사용하는 친구가 있었다.
!stackusage 는 많이 사용한 모듈을 찾아준다.
UNEXPECTED_KERNEL_MODE_TRAP(7F)
Arg1 : EXCEPTION_DOUBLE_FAULT
stack limit 보다 더 큰 주소로 콜스택이 진입하여서 BSOD 발생함.
kf나 !stackusage를 이용하여 스택 메모리를 많이 사용한 모듈을 찾아서 코드를 수정해주어야한다. 커널에서는 스레드당 할당된 스택메모리가 x86 : 12k, x64 : 24k 로 제한적인데 그 이상 사용시 BSOD가 발생한다.
KF 로 확인시 20D0의 스택메모리를 과다하게 사용하는 친구가 있었다.
2018년 12월 28일 금요일
[WinDbg]hyper-v 2 세대 remote debugging 설정
hyper-v 의 2세대 VM의 remote debugging 설정은 1세대에 있던 com 포트 설정 옵션이 없고 powershell상에서 command로 설정해야 한다.
1세대에서의 com 포트 설정 옵션
2세대에서의 com 포트 설정(powershell)
1. 일단 windows는 secure boot 를 off 시켜야 커널 디버깅이 가능하다.
2. serial 통신용 comport 를 설정한다.
3. vm을 재시작한다.
1세대에서의 com 포트 설정 옵션
2세대에서의 com 포트 설정(powershell)
1. 일단 windows는 secure boot 를 off 시켜야 커널 디버깅이 가능하다.
2. serial 통신용 comport 를 설정한다.
3. vm을 재시작한다.
2018년 1월 17일 수요일
[GDB]strcpy break 가 안잡힐때(--no-builtin)
요즘 해공예(해킹 공격의 예술) 책을 보고 있다. 윈도우 개발자로 리눅스와 비교하는 재미가 쏠쏠하다. 몇번 펼쳤다가 덮기를 여러번 요즘 또 다시 보니 눈에 들어온다.
따라하다보니 shared library 함수인 strcpy에 break 를 걸었는데 책대로 되지 않았다.
break 1, 2, 3 를 차례로 찍고 실행시켰는데 break 1, 3만 걸리는걸 볼 수 있다.
소스코드를 디스어셈 해서봐도 printf는 보이는데 strcpy는 보이지 않는다.
구글신과 영접후 --no-builtin 옵션이 영향을 주고 있다는걸 알게되었다.
뭔가 간단한 함수들은 빌트인되어있는 내부 함수가 잇는것인듯...
break 잘 잡히네요. 디스어셈해서 봐도 strcpy가 잘 보이네요
이제야 좀 대화가 되는 바이너리가 됬군요...
근데 이게 컴파일러가 이렇게 빌트인된걸로 마음대로 컴파일 하면 나중에 디버깅할때 애좀 먹겠네요. 그래도 뭐 해커가 리버싱하는건 어려울수도 있고...뭐...익숙해지면 괸찮을라나요~
참고로 프로세스 뒤에 파라미터를 추가하려면
run 할때 뒤에 붙여주면 됨.
(gdb)run arg1 arg2
따라하다보니 shared library 함수인 strcpy에 break 를 걸었는데 책대로 되지 않았다.
break 1, 2, 3 를 차례로 찍고 실행시켰는데 break 1, 3만 걸리는걸 볼 수 있다.
소스코드를 디스어셈 해서봐도 printf는 보이는데 strcpy는 보이지 않는다.
구글신과 영접후 --no-builtin 옵션이 영향을 주고 있다는걸 알게되었다.
뭔가 간단한 함수들은 빌트인되어있는 내부 함수가 잇는것인듯...
break 잘 잡히네요. 디스어셈해서 봐도 strcpy가 잘 보이네요
이제야 좀 대화가 되는 바이너리가 됬군요...
근데 이게 컴파일러가 이렇게 빌트인된걸로 마음대로 컴파일 하면 나중에 디버깅할때 애좀 먹겠네요. 그래도 뭐 해커가 리버싱하는건 어려울수도 있고...뭐...익숙해지면 괸찮을라나요~
참고로 프로세스 뒤에 파라미터를 추가하려면
run 할때 뒤에 붙여주면 됨.
(gdb)run arg1 arg2
2017년 10월 12일 목요일
[windows]메모리 릭 분석방법(umdh 이용)
crash 나거나 cpu 올라가는것들은 다 windbg로 분석이 가능한데..
메모리는 당췌 해결이 안된다..메모리가 팍팍 오르면 찾기가 쉬운데 ㅎ 슬슬...오르는건지 안오르는건지..몇일 지나면 좀 올라있고 음...메모리풀을 많이 사용해서.. 이게 메모리릭인지 먼지 .... 이럴때 umdh 엄청난 놈이다 ~ Debugging Tools for Windows 안에 포함되어있다.
사용법은 아래와 같다.
1. 유저모드 스택 추적을 설정한다. 이건 gflags라는 툴로(Debugging Tools for Windows에 포함되있음)
2. umdh를 이용해서 메모리 증가 전 메모리를 캡쳐한다.
** umdh 가 callstack을 보여주기 때문에 심볼이 필요하다. 심볼을 준비하고 심볼패스를 설정해준다. 그렇치 않으면 아래와같은 warning이 뜬다. 자세한 콜스택정보가 필요치 않으면 그대로 다음으로 진행해도 된다.
> Set _NT_SYMBOL_PATH=c:\sym;C:\Windows\symbols
3. umdh를 이용해서 메모리 증가 후 메모리를 캡쳐한다.
4. umdh를 이용해서 두 메모리의 차이를 분석한다.
6. 비교분석한 결과 파일(notepadcompare.log)를 열어보면 메모리 allocation 된 곳의 콜스택정보가 나와있다. 물론 이걸로 메모리릭을 바로 알수는 없지만 언제캡쳐하든 계속 증가하면서 남아있는 메모리 블럭이 있다면~
2017년 4월 28일 금요일
[linux][symbol]리눅스 바이너리 심볼 관련 옵션
윈도우즈는 debug/release가 명확한데 linux는 심볼이 일단 그냥 들어가있다. 음...
근데 또 심볼을 추가하는 옵션이 있긴한데 도대체 무슨 차이일까?
gcc compile
> gcc test.c -o nosym.out(기본적으로 심볼이 있다. 제한적인)
> gcc -s test.c -o strip.out(공용라이브러리 정보 외 심볼이 없다)
> gcc -g test.c -o sym.out(심볼이 모두 들어있다)
> gcc test.c
> strip a.out(기본심볼이 들어있었으나 심볼 제거)
위의 결과물이 아래와 같이 나왔다.
이제 차이를 좀 보자.
심볼이 보임
-g 를 붙이면 뭘 더 할수 있을까?
nosym.out을 디버깅을 시작해보자. 뭔가 부족함이 느껴지겠지 ㅎ
변수와 소스 등이 심볼테이블이 없다고 보이지 않는다.
sym.out을 디버깅해보자.
요차이군요 ㅎ 다보임~
근데 또 심볼을 추가하는 옵션이 있긴한데 도대체 무슨 차이일까?
gcc compile
> gcc test.c -o nosym.out(기본적으로 심볼이 있다. 제한적인)
> gcc -s test.c -o strip.out(공용라이브러리 정보 외 심볼이 없다)
> gcc -g test.c -o sym.out(심볼이 모두 들어있다)
> gcc test.c
> strip a.out(기본심볼이 들어있었으나 심볼 제거)
위의 결과물이 아래와 같이 나왔다.
이제 차이를 좀 보자.
심볼이 보임
심볼이 없고 공유 라이브러리에 대한 정보정도는 보임심볼이 보임
-g 를 붙이면 뭘 더 할수 있을까?
nosym.out을 디버깅을 시작해보자. 뭔가 부족함이 느껴지겠지 ㅎ
변수와 소스 등이 심볼테이블이 없다고 보이지 않는다.
sym.out을 디버깅해보자.
요차이군요 ㅎ 다보임~
2017년 4월 13일 목요일
[linux] process가 로드한 library 확인
윈도우에서는 process explorer라는 훌륭한 툴이 있는데
linux는 process explorer를 어떤 명령어로 대신할 수 있는지..
하나하나 알아가는 중이다. 막막하다 ㅎ
일단 공유 라이브러리에 대한 종속성은 ldd/readelf/objdump등을 통하여 확인이 쉬웠다.
하지만 동적라이브러리에 대한 확인은 되지 않았다.
그도 그럴것이 프로세스 실행후에야 디펜던시가 보일테니...
pid를 잡고 볼수 있는 뭔가가 있을거 같은데...빙고~! ㅋ
>pldd pid
위 명령어로 확인했다.
하지만 로드됬는지만 확인할 수 있을뿐 많은 정보가 있진 않다.
필요해지면 다시 찾아보자 ㅎ 일단 이걸로 만족 ~
linux는 process explorer를 어떤 명령어로 대신할 수 있는지..
하나하나 알아가는 중이다. 막막하다 ㅎ
일단 공유 라이브러리에 대한 종속성은 ldd/readelf/objdump등을 통하여 확인이 쉬웠다.
하지만 동적라이브러리에 대한 확인은 되지 않았다.
그도 그럴것이 프로세스 실행후에야 디펜던시가 보일테니...
pid를 잡고 볼수 있는 뭔가가 있을거 같은데...빙고~! ㅋ
>pldd pid
위 명령어로 확인했다.
하지만 로드됬는지만 확인할 수 있을뿐 많은 정보가 있진 않다.
필요해지면 다시 찾아보자 ㅎ 일단 이걸로 만족 ~
2017년 4월 3일 월요일
[linux]core dump 생성 및 분석 방법
리눅스는 디버깅이 쉽지 않다. 오랫동안 윈도우 환경에서 개발을 해온 나는 참..답답하다..
크래쉬가 나고 segmentation fault (core dumped) 라는 메세지가 뜨는데..당췌 디버깅을 어떻게 해야하는지...로그파일로는 한계가 있다.
검색을 하다보니 core 파일을 생성하여 gdb로 디버깅이 가능하다 ㅎ 이런~ 좋은 방법이~
하지만 크래쉬가 났는데 core dumped라고 하는데 core파일이 없다...
코어파일 사이즈가 0인지 확인한다.(ulimit -a)
아래와 같이 코어 파일 사이즈를 변경합니다.
이제 크러쉬후에 core.xxxx라는 코어 파일이 생성되었음을 볼수 있습니다.
자 이제 core파일을 gdb로 분석해봅시다.
WinDbg와 분석 포인트는 유사해서 어렵진 않네요 깊이가 문제겠지만 ㅎ
#gdb 실행프로세스 코어파일 ->코어파일 분석시작
#bt -> call stack
#f n -> n frame으로 이동
#list -> 해당 스택의 소스 보여줌
#info locals -> 로컬 변수값 보여줌
#p val -> val 변수 값 보여줌
#x address -> 해당 주소의 값 보여줌
크래쉬가 나고 segmentation fault (core dumped) 라는 메세지가 뜨는데..당췌 디버깅을 어떻게 해야하는지...로그파일로는 한계가 있다.
검색을 하다보니 core 파일을 생성하여 gdb로 디버깅이 가능하다 ㅎ 이런~ 좋은 방법이~
하지만 크래쉬가 났는데 core dumped라고 하는데 core파일이 없다...
코어파일 사이즈가 0인지 확인한다.(ulimit -a)
아래와 같이 코어 파일 사이즈를 변경합니다.
이제 크러쉬후에 core.xxxx라는 코어 파일이 생성되었음을 볼수 있습니다.
자 이제 core파일을 gdb로 분석해봅시다.
WinDbg와 분석 포인트는 유사해서 어렵진 않네요 깊이가 문제겠지만 ㅎ
#gdb 실행프로세스 코어파일 ->코어파일 분석시작
#bt -> call stack
#f n -> n frame으로 이동
#list -> 해당 스택의 소스 보여줌
#info locals -> 로컬 변수값 보여줌
#p val -> val 변수 값 보여줌
#x address -> 해당 주소의 값 보여줌
2016년 8월 19일 금요일
[WinDbg]윈도우 프로세스의 스레드별 cpu 사용량 확인
개발자로 생활한지는 꾀 됬는데..
cpu 100치는 현상은 항상 당황스럽다..
개발시 나오면 찾기 쉬우나 사이트에서 일어나는 현상이면..ㅠ
사실 생각보다 많이 당해보진 않았다. ㅎ
이런 현상 발생하면 큰일난다 ㅋㅋ 서버보안을 담당중이라..
여튼 프로세스가 100치는것 까진 쉽게 알아낼 수 있다 . 작업관리자만 봐도..
process explorer를 봐도..
하지만 어느 스레드때문에 발생하는건지는 스레드마다 호출스택 다 뒤져서 확인하는 수밖에 없는줄 알았다....
근데 windbg의 무한한 기능중에 좋은 기능이 있어 소개한다.
>!runaway
아래와 같은 스레드를 두개를 돌리는 프로세스를 windbg로 실행시켰다. 물론 cpu는 ThreadFunc 스레드에 의해서 100을 쳤다.
이상황에서 windbg에서 !runaway를 실행하였다.
스레드에 대한 cpu 점유 시간을 보여주고 잇다. cpu 점유시간이 제일 높은 스레드가 cpu 사용량이 많은 스레드이므로 위에서는 1번 스레드임을 알수 있다. 1번 스레드의 콜스택을 살펴보니 역시 ThreadFunc이 있음을 확인할 수 있다.^^
2016년 7월 14일 목요일
[minifilter dirver]BUGCHECK 103 MUP_FILE_SYSTEM
mini filter driver에서 precallback에서 FltQueryInformationFile 호출시 난 에러이다..
멘붕...irql 레벨도 아니고 메모리 오류도 아니고...쩝 첨보는 에러다...
PRECALLBACK이라 IRP_MJ_CREATE 가 끝나지 않아 파일 정보를 쿼리할 수 없어서 나는 에러였다...까먹을까봐 정리해본다..물론 IRP_MJ_CREATE 에서는 POST에서는 문제가 없으나 PRE에서는 제거하였다.
오늘또 BUGCHECK에 대해 하나 알았네..휴...윈도우와 소통하기 힘듬..
멘붕...irql 레벨도 아니고 메모리 오류도 아니고...쩝 첨보는 에러다...
PRECALLBACK이라 IRP_MJ_CREATE 가 끝나지 않아 파일 정보를 쿼리할 수 없어서 나는 에러였다...까먹을까봐 정리해본다..물론 IRP_MJ_CREATE 에서는 POST에서는 문제가 없으나 PRE에서는 제거하였다.
오늘또 BUGCHECK에 대해 하나 알았네..휴...윈도우와 소통하기 힘듬..
2015년 10월 27일 화요일
[WinDbg]GetLastError 보는 방법
LoadLibrary를 했는데 리턴값이 0이면 GetLastError로 찍어봐야되는데요
코드수정없이 WinDbg에서 바로 볼수 있는 방법이 있습니다.
TEB 구조체의 LastErrorValue를 이용하는 것입니다.
아래는 LoadLibrary를 호출한 후에 레지스트리에 리턴값(rax)가 0임을 확인한 내용입니다.
이때 teb를 확인해보겠습니다.
LastErrorValue가 5가 나왔네요
이경우는 라이브러리를 로드할려고 했으나 권한부족으로 로드를 못한 경우였습니다.
어떤 경우에 권한이 부족할까?
NETWORK SERVICE 계정으로 돌고 있는 서비스에서 C:\TEST 폴더 밑의 특정 라이브러리를 로드하려고 시도해봤는데요. 계속 잘 되다가 해당 폴더를 공유를 걸고 나니 로드가 안되더군요. 폴더 사용권한을 확인해봤더니 공유를 걸면서 보안설정이 변경이 되서 그러했습니다.
authenticated users를 추가해주어서 저는 해결했는데요 보안이 중요하면 network service 계정만을 추가하면 되겠죠~
코드수정없이 WinDbg에서 바로 볼수 있는 방법이 있습니다.
TEB 구조체의 LastErrorValue를 이용하는 것입니다.
아래는 LoadLibrary를 호출한 후에 레지스트리에 리턴값(rax)가 0임을 확인한 내용입니다.
이때 teb를 확인해보겠습니다.
LastErrorValue가 5가 나왔네요
이경우는 라이브러리를 로드할려고 했으나 권한부족으로 로드를 못한 경우였습니다.
어떤 경우에 권한이 부족할까?
NETWORK SERVICE 계정으로 돌고 있는 서비스에서 C:\TEST 폴더 밑의 특정 라이브러리를 로드하려고 시도해봤는데요. 계속 잘 되다가 해당 폴더를 공유를 걸고 나니 로드가 안되더군요. 폴더 사용권한을 확인해봤더니 공유를 걸면서 보안설정이 변경이 되서 그러했습니다.
authenticated users를 추가해주어서 저는 해결했는데요 보안이 중요하면 network service 계정만을 추가하면 되겠죠~
[WinDbg]error InitTypeRead( TEB ) 해결방법
디버깅중 teb 값을 보고 싶은데 InitTypeRead 에러가 나고 볼수가 없어서 봤더니 심볼이 맞지 않는다는 설명이네요....음 teb command는 심볼이 필요하네요...teb 구조체 정보가 있어야 되서 그런가봅니다....
그래서 lm 명령어로 ntdll심볼정보를 봤더니 아래와 같이 pdb가 아니고 그냥 dll 패스가 적혀있네요...export symbols... 라고 되있고 이건 무슨 의미인지 알고싶지만 알게될때 정리하도록 하고 계속 진행해보도록 하겠습니다. 일단 teb가 되는게 목적이라..^^;
먼진 모르지만 원하는 pdb 파일이 로드되있진 않으므로 다시 reload를 해보았습니다.
reload 하고 다시 ntdll 정보를 보니 private pdb symbols라고 되있네요..제가 원하던 pdb 입니다.
그럼 다시 teb를 보겠습니다. 이제 teb값이 제대로 보이네요~ ^^
그래서 lm 명령어로 ntdll심볼정보를 봤더니 아래와 같이 pdb가 아니고 그냥 dll 패스가 적혀있네요...export symbols... 라고 되있고 이건 무슨 의미인지 알고싶지만 알게될때 정리하도록 하고 계속 진행해보도록 하겠습니다. 일단 teb가 되는게 목적이라..^^;
먼진 모르지만 원하는 pdb 파일이 로드되있진 않으므로 다시 reload를 해보았습니다.
reload 하고 다시 ntdll 정보를 보니 private pdb symbols라고 되있네요..제가 원하던 pdb 입니다.
그럼 다시 teb를 보겠습니다. 이제 teb값이 제대로 보이네요~ ^^
2015년 9월 25일 금요일
[상속]상속과 메모리 맵
상속의 개념은 알고 있었으나 상속되었을시 메모리 구조에 대해서는 최근 후킹시 펑션 포인터를 얻어오기 위해서 생각을 해보게 되었습니다.
이전에 캐스팅 연산자 포스팅에서 reinterpret_cast에 대해서 논하면서 테스트 해본 내용이
상속받은 클래스를 reinterpret_cast로 캐스팅 해서 기존 클래스 얻을 수 있는가 하는 것이었습니다. 기존 클래스를 얻을 수 있을거란 내 예상과는 달리 기존 클래스를 얻지 못한 경우도 있어서 확실한 내용이 아니라 포스팅에서는 언급하지 않았던 부분이었다.
여기서는 상속하였을때 파생클래스의 매모리 맵 구조를 알아보고 왜 그런결과가 있었는지에 대해 정리해보았다.
1. 단일상속
단일 상속은 클래스 하나를 상속받은 경우이며 두 클래스의 메모리 맵은 아래와 같다.
First 클래스를 상속받은 Second 클래스입니다.
WinDbg에서 메모리 구조를 확인하였습니다.
watch 창에서 Second 클래스 x에 대해서 각각 a, b, a1, b1에 대한 멤버 변수의 메모리 위치를 확인하였습니다. x 인스턴스는 0x00635748이고 멤버변수는 순서대로 배치되 있음을 확인할 수 있습니다.
이번엔 Third 클래스를 만들어서 Second 클래스를 다시 상속받아 보겠습니다.
x 인스턴스는 0x00575748 이고 멤버변수는 상속받은 순서대로 배치되 있음을 확인할 수 있습니다.
Third 클래스의 메모리구조를 보면 위 4개는 Second 클래스의 메모리 구조와 같고 위 4개는 First 클래스의 메모리구조와 같음을 확인할 수 있습니다.
그러므로 Third 클래스의 인스턴스를 First 클래스에 캐스팅하면 First 클래스가 되고 Second클래스에 상속하면 Second 클래스가 됨을 알 수 있습니다. 하지만 다중상속에서는 달라지는데요 아래에서 확인해보겠습니다.
2. 다중상속
다중상속은 하나가 아닌 여러개의 클래스로 부터 상속을 받는 경우를 의미합니다. 메모리맵을 확인해보겠습니다.
Third 클래스 x의 인스턴스는 0x00795748이고 역시 상속받은 순서대로 변수 배치가 되있음을 확인할 수 있다. 하지만 First클래스나 Second 클래스로 캐스팅할때는 얘기가 달라집니다.
위의 그림에서 보듯이 Second 클래스가 Third 클래스의 인스턴스 시작위치와 같지 않음을 알 수 있습니다. Second 클래스는 First 클래스를 포함하고 있지 않기 때문에 위와 같은 구조가 됩니다. 따라서 reinterpret 캐스팅시(in_s1 = 0x00795748)와 static 캐스팅시(in_s = 0x00795750) Second의 인스턴스 값이 다르게 되고 reinterpret 캐스팅은 다중상속에서는 매우 위험함을 알 수 있습니다.
3. 다이아몬드상속
다중상속 중 base 클래스가 같은 클래스를 다중상속받는것을 이야기합니다. 어떤일이 일어날가요? 중복되는 부분이 있을듯 한데요.
base 클래스인 First 클래스가 먼저 배치되고 그다음 상속받은 순서대로 Second, Third의 순서로 메모리에 배치됨을 볼 수 있다.
클래스에 변수만 있다면 아직까지는 순조롭고 원하던 데로 배치가 된듯합니다. 하지만 First 클래스에 함수가 있으면 어떻게 될까요?
First 클래스에 First_func 함수를 추가했더니 Second클래스와 Third 클래스에 모두 포함되게 되어 Fourth에서는 찾을 수가 없다는 컴파일 에러가 발생합니다.
이를 해결하기 위해서 가상상속이 나타나게 됩니다. 그럼 가상상속에 대해서 알아보겠습니다.
4. 가상상속
위에서처럼 base가 같은 클래스를 다중으로 상속 받을경우 base클래스는 한번만 상속받게 하기 위해서 virtual 키워드를 사용하여 가상상속을 사용합니다.
위의 코드처럼 virtual로 base클래스인 First클래스를 상속받았더니 x->Fust_func의 모호함이 사라지고 원하던대로 상속받은 모든 함수의 사용이 자유롭습니다.
이전에 캐스팅 연산자 포스팅에서 reinterpret_cast에 대해서 논하면서 테스트 해본 내용이
상속받은 클래스를 reinterpret_cast로 캐스팅 해서 기존 클래스 얻을 수 있는가 하는 것이었습니다. 기존 클래스를 얻을 수 있을거란 내 예상과는 달리 기존 클래스를 얻지 못한 경우도 있어서 확실한 내용이 아니라 포스팅에서는 언급하지 않았던 부분이었다.
여기서는 상속하였을때 파생클래스의 매모리 맵 구조를 알아보고 왜 그런결과가 있었는지에 대해 정리해보았다.
1. 단일상속
단일 상속은 클래스 하나를 상속받은 경우이며 두 클래스의 메모리 맵은 아래와 같다.
First 클래스를 상속받은 Second 클래스입니다.
WinDbg에서 메모리 구조를 확인하였습니다.
watch 창에서 Second 클래스 x에 대해서 각각 a, b, a1, b1에 대한 멤버 변수의 메모리 위치를 확인하였습니다. x 인스턴스는 0x00635748이고 멤버변수는 순서대로 배치되 있음을 확인할 수 있습니다.
이번엔 Third 클래스를 만들어서 Second 클래스를 다시 상속받아 보겠습니다.
x 인스턴스는 0x00575748 이고 멤버변수는 상속받은 순서대로 배치되 있음을 확인할 수 있습니다.
Third 클래스의 메모리구조를 보면 위 4개는 Second 클래스의 메모리 구조와 같고 위 4개는 First 클래스의 메모리구조와 같음을 확인할 수 있습니다.
그러므로 Third 클래스의 인스턴스를 First 클래스에 캐스팅하면 First 클래스가 되고 Second클래스에 상속하면 Second 클래스가 됨을 알 수 있습니다. 하지만 다중상속에서는 달라지는데요 아래에서 확인해보겠습니다.
다중상속은 하나가 아닌 여러개의 클래스로 부터 상속을 받는 경우를 의미합니다. 메모리맵을 확인해보겠습니다.
위의 그림에서 보듯이 Second 클래스가 Third 클래스의 인스턴스 시작위치와 같지 않음을 알 수 있습니다. Second 클래스는 First 클래스를 포함하고 있지 않기 때문에 위와 같은 구조가 됩니다. 따라서 reinterpret 캐스팅시(in_s1 = 0x00795748)와 static 캐스팅시(in_s = 0x00795750) Second의 인스턴스 값이 다르게 되고 reinterpret 캐스팅은 다중상속에서는 매우 위험함을 알 수 있습니다.
3. 다이아몬드상속
다중상속 중 base 클래스가 같은 클래스를 다중상속받는것을 이야기합니다. 어떤일이 일어날가요? 중복되는 부분이 있을듯 한데요.
base 클래스인 First 클래스가 먼저 배치되고 그다음 상속받은 순서대로 Second, Third의 순서로 메모리에 배치됨을 볼 수 있다.
클래스에 변수만 있다면 아직까지는 순조롭고 원하던 데로 배치가 된듯합니다. 하지만 First 클래스에 함수가 있으면 어떻게 될까요?
First 클래스에 First_func 함수를 추가했더니 Second클래스와 Third 클래스에 모두 포함되게 되어 Fourth에서는 찾을 수가 없다는 컴파일 에러가 발생합니다.
이를 해결하기 위해서 가상상속이 나타나게 됩니다. 그럼 가상상속에 대해서 알아보겠습니다.
4. 가상상속
위에서처럼 base가 같은 클래스를 다중으로 상속 받을경우 base클래스는 한번만 상속받게 하기 위해서 virtual 키워드를 사용하여 가상상속을 사용합니다.
위의 코드처럼 virtual로 base클래스인 First클래스를 상속받았더니 x->Fust_func의 모호함이 사라지고 원하던대로 상속받은 모든 함수의 사용이 자유롭습니다.
2015년 8월 7일 금요일
[WinDbg] 조건부 브레이크포인트 (breakpoints with commands)
windbg로 rdp 리버싱중 rdpwsx!WsxIcaStackIoControl의 38009b 파라미터를 넣었을때만 리버싱을 진행하고 싶었다.
하지만 StackIoControl은 입력 파라미터에 따른 output 데이타가 다른 함수로 많은 정보를 이 함수로 얻어내고 있는 듯 보였다. 하지만 나는 38009b 일때의 정보만이 관심이 있을뿐...
조건을 걸어 브레이크를 걸수 있으면 좋을거 같단 생각이 들었다.
아래 사이트는 common windbg commands 이다.
http://windbg.info/doc/1-common-cmds.html
windbg에는 breakpoints를 걸때 사용할 수 있는 options 및 commands를 지원하여 확장성 및 편의성을 높이고 있었다.
bp [Addr][Options]
bp [Addr]["CmdString"]
단순히 hitting 수로 거는 옵션을 제공하고 조건문을 넣을수 있는 cmdstring을 지원했다.
나는 bp rdpwsx!WsxIcaStackIoControl ".if(r9==0x38009b){} .else{gc}" 로 원하는 조건에 맞는 순간을 잡을 수 있었다.
시스템 리버싱할때는 레지스터값을 주로 보겠지만 드라이버에서 변수값을 조건에 넣고 싶을때는 아래와 같이 사용한다.
bp Function ".if@@(변수==값){} .else{gc}"
좀 더 자세한 조건부 사용법은 아래 사이트를 참고하자.
https://msdn.microsoft.com/en-us/library/windows/hardware/ff556853(v=vs.85).aspx
좀 더 많은 조건부를 사용해보고 다시 정리하도록 해야겠다.
하지만 StackIoControl은 입력 파라미터에 따른 output 데이타가 다른 함수로 많은 정보를 이 함수로 얻어내고 있는 듯 보였다. 하지만 나는 38009b 일때의 정보만이 관심이 있을뿐...
조건을 걸어 브레이크를 걸수 있으면 좋을거 같단 생각이 들었다.
아래 사이트는 common windbg commands 이다.
http://windbg.info/doc/1-common-cmds.html
windbg에는 breakpoints를 걸때 사용할 수 있는 options 및 commands를 지원하여 확장성 및 편의성을 높이고 있었다.
bp [Addr][Options]
bp [Addr]["CmdString"]
단순히 hitting 수로 거는 옵션을 제공하고 조건문을 넣을수 있는 cmdstring을 지원했다.
나는 bp rdpwsx!WsxIcaStackIoControl ".if(r9==0x38009b){} .else{gc}" 로 원하는 조건에 맞는 순간을 잡을 수 있었다.
시스템 리버싱할때는 레지스터값을 주로 보겠지만 드라이버에서 변수값을 조건에 넣고 싶을때는 아래와 같이 사용한다.
bp Function ".if@@(변수==값){} .else{gc}"
좀 더 자세한 조건부 사용법은 아래 사이트를 참고하자.
https://msdn.microsoft.com/en-us/library/windows/hardware/ff556853(v=vs.85).aspx
좀 더 많은 조건부를 사용해보고 다시 정리하도록 해야겠다.
피드 구독하기:
글 (Atom)



