Contents
1. 새싹교실 ¶
- 임시명 세싹반입니다.
- 수업시간: 매주 화 15:00~16:00
금 12:00~13:00
- 수업과목: everything you want
이 외에 원할때 언제든 찾아오면 됩니다.
3. feedback ¶
- 새싹교실이 ZeroPage에서 시행되는만큼 4F(ThreeFs + Future Action Plan)에 맞게 feedback을 작성합니다.
- Facts, Feelings, Findings, Future Action Plan. 즉, 사실, 느낀 점, 깨달은 점, 앞으로의 계획.
- 예를 들어 지난주에 돈가스를 먹은 것에 대해 후기를 쓴다면 : "지난주에 강남에 가서 하나에 5만원하는 돈가스를 먹었다.(사실) 기대를 잔뜩 했는데 별로 맛이 없었다.(느낌) 강남은 땅값이 비싸서 값만 보고 엄청 맛있을거라 기대하면 안된다는 것을 알았다.(깨달은점) 다음에는 미리 인터넷에서 평을 찾아보고 별점이 높은 돈가스집을 찾아서 가봐야겠다.(앞으로의 계획)"
- 설마 이것보다 더 짧게 쓰진 않겠죠? 믿을게요
- 설마 이것보다 더 짧게 쓰진 않겠죠? 믿을게요
- Facts, Feelings, Findings, Future Action Plan. 즉, 사실, 느낀 점, 깨달은 점, 앞으로의 계획.
- feedback은 최대한 성의있게 써주세요.
- 반드시 ZeroWiki에 작성해주세요. 하위 페이지를 만드는 것도 허용합니다.
- 여러분들이 배운 내용을 정리해주세요. 학습효과가 더 커집니다.
- 반드시 ZeroWiki에 작성해주세요. 하위 페이지를 만드는 것도 허용합니다.
- 참고로 ZeroWiki는 MoniWiki Engine을 사용하며 Google Chrome이나 Mozila Firefox, Safari보다는 Internet Explorer에서 가장 잘 돌아가는 것 같습니다.
4.1.2. 수업내용 ¶
- wiki를 왜 쓰는지, 어떻게 사용하는지에 대해 배웠습니다.
- gcc 개발환경을 구축하는 법을 알아보았습니다.
1) https://www.virtualbox.org 에서 자신의 운영 체제에 맞는 VirtualBux를 설치
2) http://ftp.daum.net -> Ubuntu-releases -> 11.10 -> ubuntu-11.10-deskto-amd64.iso 다운
3) Virtualbox실행 -> 새로 만들기 -> 운영체제 : Linux 버전 : Ubuntu -> 메모리1024MB로 설정하고 나머지 디폴트 설치
4) 만들어진 ubuntu 실행 -> 설치 미디어로 ISO파일 마운트 -> 설치
(설치 도중에 설정해줘야되는 것 : 글자판 배치를 한국어(101/104키 호환)으로 해야됨!)
- gcc로 hello world를 컴파일 해보았습니다.
1) 우분투 소프트웨어 센터에서 gcc 검색 & 설치
2) 원하는 경로에 빈 문서 만들기 (확장자는 .c로 해주세요)
3) 해당 문서에 코드 작성
4) terminal 실행 -> .c 파일이 있는 경로로 이동 (ls와 cd를 이용합니다.)
5) gcc로 컴파일을 합니다. (gcc 파일명.c -o 원하는파일명 -std=c99) 해당 예제외에 추가로 여러 옵션을 줄수 있습니다.
6) 컴파일된 파일을 실행합니다. (./파일명)
- w3schools를 소개했습니다. (www.w3schools.com)
- 협업의 중요성에 대해 이야기했습니다.
- 문서작성, 버전관리, 주석처리 등 아직은 실감이 안나겠지만 처음부터 습관을 들이는것이 중요합니다.
- 문서작성, 버전관리, 주석처리 등 아직은 실감이 안나겠지만 처음부터 습관을 들이는것이 중요합니다.
4.1.3. 숙제 ¶
- wiki 사용법 익히기
1) 자기 페이지 만들기 - 로그인후 자신의 이름으로 검색하여 페이지를 작성하시면 됩니다. 기본적인 프로필과 하고싶은말을 적어주세요.
2) 후기 작성 - 아래 회고란에 편집을 눌러 후기를 남겨주시면됩니다. 위의 feedback 항목을 참고하세요.
- gcc 개발환경 구축하기
1) virtual box로 linux 설치 후 hello world 작성하고 컴파일하여 스크린샷을 강사 메일로 보내주세요.
4.1.4. 권장사항 ¶
- 숙제는 아니지만 해봤으면 합니다:D
1) w3schools에서 html파트 읽고 실습해보기
2) linux의 다양한 명령어 검색해보기
3) gcc의 옵션 검색해보기
4.1.5. 후기 ¶
- 새싹 첫시간을 가졌습니다. 다른 새싹반들과는 다른 커리큘럼으로 진행을 해야해서, 무엇을 수업해야할지 고민이 많습니다(멘붕 일보직전). 학교수업 듣는것처럼 하지말고 자유로운 분위기에서 진행되면 좋겠습니다. - 정의정
- 새싹 첫시간을 가졌습니다. 캡스톤실도 처음 들어가봐서 많이 신기했습니다. 처음 듣는 용어, 처음 보는 화면들 생소한게 많지만 재미있을 것 같아서 기대가 됩니다. 숙제도 권장사항도 열심히 해보겠습니다. 앞으로 잘 부탁드립니다. - 권영기
- 새싹 첫시간을 가졌습니다. 이곳 Wiki가 매우 흥미로웠고, 캡스톤실에 대해서도 궁금점을 해소하여 좋았습니다. 이름만 들어보고 좀처럼 볼 일이 없던 것들을 보게되어 좋았습니다. 앞으로 잘 부탁드립니다. - 김희성
- 숙제를 수행하기 위해 버추얼 박스를 설치하였습니다. 설치파일이 정상적으로 실행 않는 문제가 있었는데 인터넷으로 강제 압축해제하는 방법을 듣고 7z으로 압축을 해제하는 방법으로 해결하였습니다. 데몬이 없어 iso파일도 7z으로 풀었습니다. - 김희성
4.2.2. 수업내용 ¶
- 숙제에 대해서 이야기 나누었습니다.
1) gcc 컴파일 옵션이 어려웠습니다. - gcc 컴파일 옵션의 대부분은 컴파일에 크리티컬한 것이 아니라 사용자에게 정보를 제공하는 것이 목적입니다. 그냥 안써도 되요
- 네트워크에 대하여 간단히 알아보았습니다.
1) 우리가 사용하는 인터넷은 패킷 스위치 방식으로 소포에 주소를 써서 목적지에 보내는 것 처럼 작동하는 네트워크 입니다.
2) 인터넷 프로토콜의 계층도에 대해 알아보았습니다.
- app : 우리가 실제로 사용하는 서비스를 제공하는 계층입니다. http, smtp, ftp등이 있습니다.3) 하지만 우리가 이 모든것을 반드시 알아야 통신 프로그램을 할 수 있는것은 아닙니다.
- transport : 데이터를 어떻게 보낼지 결정하는 계층입니다. 데이터를 어떻게 묶어서 보낼지, 오류처리는 어떻게 할지에 대해 결정합니다. TCP/UDP등이 있습니다.
- ip : 호스트와 호스트, 즉 출발지에서 목적지까지 데이터 묶음(패킷)을 전달하는 역할을 합니다. 라우터가 있습니다.
- link : 노드와 노드간에 데이터를 주고받는 역할을 합니다. 스위치, 브릿지등이 포함됩니다.
- physical : 비트들을 물리적으로 이동시키는 역할을 합니다. 유선의 경우 다양한 케이블, 무선일 경우 공기가 매체가 되겠네요.
- 이런 기능들을 단계별로 나눈 이유는, 자신의 하위 계층의 구현내용이 어떤지 잘 몰라도 그 기능을 사용할 수 있도록 하기 위해서입니다.4) 그럼 소켓은 무엇인가요?
- 즉, 소켓 프로그래밍도 해당 함수와 하위 함수들의 작동원리를 잘 모르더라도 어떤 기능을 하는지만 알면 쉽게 통신 프로그래밍을 할 수 있습니다.
- 인터넷 소켓(Internet socket, socket' 혹은 network socket 라고 부르기도 한다)은 네트워크로 연결되어 있는 컴퓨터의 통신의 접점에 위치한 통신 객체다.5) 자세한 사항은 http://forum.falinux.com/zbxe/?document_srl=441104 를 참고하세요.
네트워크 통신을 위한 프로그램들은 소켓을 생성하고, 이 소켓을 통해서 서로 데이터를 교환한다. - wikipedia- 는 훼이크고 :P 간단히 설명하면 서버와 클라이언트가 byte stream을 주고 받는 것을 마치 파일 입출력을 하듯 해주는 것입니다.
파일입출력 소켓 파일구조체생성 소켓 생성 fopen() connect() read()/write() read()/write() close() close()
4.2.3. 숙제 ¶
- c로 소켓짜기
1) 위 참조 페이지의 소스를 참고하여 서버와 클라이언트 코드를 직접 짜봅시다.
2) 요구사항은 클라이언트에서 보내온 메시지를 서버측에서 대문자로 바꿔서 다시 클라이언트에게 보내주는 것입니다.
3) 난이도가 다소 높을 수 있으므로 완성을 요구하지 않습니다. 한번 해보고 금요일날 다시 이야기 나눠보겠습니다.
4) 리눅스 환경에서 gcc를 사용해 봅시다.
5) 어려운 점은 카톡이나 위키 댓글을 이용해 주세요.
4.2.5. 후기 ¶
- 이 반의 수업내용을 보니 저도 참여하고 싶어지는군요 =_=ㅋ 재밌겠네요 ㅋㅋ - 김태진
- 소켓 프로그래밍을 시작하였습니다. 네트워크에 대해 전혀 지식이 없는 친구들에게 짧은 시간안에 어떻게 개념을 알려주나 많이 고민했고 결과는 역시 fail이었던 것 같습니다. 짧은 시간에 이론적인 부분을 하는건 강사나 새싹이나 멘탈이 찢어지는 일인 것 같습니다..... 그리고 화요일 시간을 조정해야될 것 같네요.. 새싹 수업이 선대 끝나고 바로 있어서 희성이가 꾸벅꾸벅 졸았습니다. 선대를 안들은자만이 돌을 던지라. - 정의정
- 오 C로 소켓 프로그래밍은 처음 보네요 재미있을듯ㅋㅋ - 신기호
- 이 반 빡세네요 ㅋㅋㅋㅋ 네트워크 가르치기 힘들겠다… 난감할땐 맨땅에 헤딩하는 것 그것이 진정한 공돌이의 길이라고 둘러대는 게 좋을듯… - 김수경
- 졸면서 들어도 이해가 가능할 정도로 요점이 잘 정리된 수업이었습니다. - 김희성
- 소켓 프로그래밍에 대해서 배웠습니다. 수업 내용을 잘 따라가지 못할 것이 두려워 걱정을 많이 했는데 선생님이 설명을 잘 해주셔서 수업 내용을 이해 할 수 있었습니다. 옛날에 자격증 딸 때 보았던 단어들이 막 나오니까 신기했습니다. 다음 수업까지 복습을 열심히 해야될 것 같습니다. 아 그리고 선생님의 강의 노트가 굉장히 탐이 났습니다. - 권영기
- 공감... - 김희성
- 오피에서 숙제를 했습니다. VS로 하려니까 뭔가 막 오류가 나는데 고치지는 못하겠고 그래서 우분투를 깔아서 시도를 했네요. 용어가 익숙하지 않아서 그런지 함수 설명을 봐도 한번에 와닿지 않아서 힘들었습니다. 아 그리고 숙제를 하다가 생긴 문제인데요. 서버 프로그램을 처음 실행했을 때는 괜찮은데 두 번째로 실행했을 때는 Bind에러가 나네요. 그래서 매번 실행할 때마다 포트값을 수정해야했습니다. 왜 이런 문제가 생긴걸까요? - 권영기
- 권영기 학생이 맞닥트린 bind 오류는, 해당 포트에 내가 가서 눌러앉으려고(bind하려고) 가 보니까 다른 놈이 이미 차지하고 있어서 bind하지 못했다는 오류입니다. 프로그램에서 bind한 후 다 쓰고 나서 bind를 해제하지 않으면 이런 일이 발생합니다. bind 해제 코드를 꼭 넣도록 하세요. - 황현
- 잠깐 사이에 답글이 올라오다니! 감사합니다. - 권영기
- 자세한 해결 방법입니다. 소켓을 생성하고나서 바로 setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, &anyIntegerVariableThatContainsNonZero, sizeof(anyIntegerVariableThatContainsNonZero)); 함수를 호출하면 이 소켓의 생명이 다하는 순간 해당 포트에 자리가 나게 됩니다. - 황현
- 자세한 해결 방법입니다. 소켓을 생성하고나서 바로 setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, &anyIntegerVariableThatContainsNonZero, sizeof(anyIntegerVariableThatContainsNonZero)); 함수를 호출하면 이 소켓의 생명이 다하는 순간 해당 포트에 자리가 나게 됩니다. - 황현
- 권영기 학생이 맞닥트린 bind 오류는, 해당 포트에 내가 가서 눌러앉으려고(bind하려고) 가 보니까 다른 놈이 이미 차지하고 있어서 bind하지 못했다는 오류입니다. 프로그램에서 bind한 후 다 쓰고 나서 bind를 해제하지 않으면 이런 일이 발생합니다. bind 해제 코드를 꼭 넣도록 하세요. - 황현
- 공감... - 김희성
4.3.2. 수업내용 ¶
- 지난 시간에 수업한 내용에 대해 이야기 했습니다.
1) 포트의 중복을 어떻게 해결하나요?
- 서버소켓의 경우 창구의 역할을 하기때문에 클라이언트에서 서버로 요청이 올 경우 별도의2) 하나의 클라이언트가 다수의 서버에 연결을 요청하는 경우에는 어떻게 될까요?
포트를 열어 통신 서비스를 제공합니다.- 위와 같이하면 하나의 서버에 다수의 클라이언트가 연결하는 상황에 충분히 대처할 수 있습니다.
- 숙제입니다. 실험해보세요3) 서버와 클라이언트를 따로두니 너무 불편합니다. 어떻게 방법이 없을까요?
- thread를 이용하여 서버와 클라이언트를 한 어플리케이션 안에서 사용하는4) 서버나 클라이언트 양쪽 다 연결되있기에는 제약사항이 너무 큽니다.
concurrent 프로그래밍을 다음시간부터 하겠습니다.
- 양방향 통신중 한쪽이 off-line상태인 경우에도 메시지의 전송과 수령이 가능하도록
서버를 두어 push형식으로 메시지를 주고 받습니다. 이를 C2DM이라고 합니다.
- Thread에 대해서 알아보았습니다.
- thread가 어떤 것인지 왜사용하는지 어떻게 사용하는지 간단히 소개하였습니다.
다음시간에 어떻게 프로그래밍 할 것인지 같이 알아보겠습니다.
4.3.3. 숙제 ¶
- 다수의 클라이언트가 하나의 서버에 연결 요청하는 시뮬레이션
- terminal을 여러개 실행시켜 실험을 진행해 보세요.
- 하나의 클라이언트가 다수의 서버에 연결 요청하는 경우도 해봅시다.
- 지난 숙제에서는 클라이언트가 한번만 메시지를 전송하고 받았는데, 지속적으로 전송하도록 구현해봅시다.
- 클라이언트에 while문만 추가하면 간단할 것 같습니다.
4.3.5. 후기 ¶
- 컴파일이 안되서 인터넷으로 확인해보니 다중 스레드를 쓰려면 gcc에 옵션 -lpthread를 주어야하는군요. - 김희성
- 데이터 처리에 대하여 좀 더 검색하였는데 기본적으로 send된 정보는 버퍼에 계속 쌓이며, recv가 큐처럼 버퍼를 지우면서 읽는다고 되어있었습니다. 반면 read와 같은 파일포인터 함수로 읽으면 버퍼를 지우지않고 파일포인터만 이동하는 것 같더군요. recv도 옵션을 변경하면 버퍼에 계속 누적해서 보관할 수 있는거 같습니다.
- 참고 사이트 :
- 소캣 옵션 참고 사이트 (close시 bind 해제 설정)
- 예제가 이미지인 줄 알았는데 박스였군요. - 김희성
- 스레드 실행 시점이 그때그때 달라서 값이 변하는 변수의 포인터를 인자로 주면 안되는군요. 그것 때문에 고생했습니다. - 김희성
- 숙제 완료 - 김희성
- 주말간 바빠서 위키접속을 못하는 동안 엄청난 일이 벌어졌군.. 절대 저런 숙제를 내준 기억은 없는데.... - 정의정
- 할 줄 아는 거라고 생각했는데 막상 하려니까 되질 않네요. 좀 더 열심히 해야될 것 같네요. - 권영기
4.4.2. 수업내용 ¶
- 숙제에 대해 이야기 했습니다.
1) 권영기 학생이 클라이언트 쪽에서 메시지가 한번만 보내지는 현상때문에 멘붕
-> 서버측에서 메시지를 한번만 받고 close해버려서 생긴 결과였습니다.2) 하나의 클라이언트가 다수의 서버에 연결을 요청하는 경우
-> 직접 해보는게 숙제였는데 다들 당연히 될 것으로 예상하고 해보지 않았네요.3) 위키의 늦은 업데이트로 인한 숙제 착오
-> 주말간 강사가 너무 바빠서 위키 업데이트를 못하는동안 참사가 발생
잠깐 소개했던 thread프로그래밍을 김희성 학생이 thread로 소켓을 짜는 것인줄 알고 채팅 프로그래밍을 완성시켰네요. 강사 멘붕
- concurrent 프로그래밍에 대해 배웠습니다.
1) thread 프로그래밍
- thread의 동작 원리와 thread를 어떻게 생성하는지, 종료를 어떻게 시키는지에 대해 배웠습니다.
- 자세한 내용은 링크를 참조. http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Thread/Beginning/WhatThread
4.4.5. 후기 ¶
- 이번에도 위키 업데이트가 좀 늦었습니다. 새싹 시간도 깜빡해서 지각하고.. 점점 바빠지는 것 같네요. 시간을 좀 더 아껴써야겠다는 생각이 들었습니다. 그리고 정해진 커리큘럼대로 하는 수업이 아니라서 그냥 손에 잡히는대로 필요한 지식을 전수하기로 했습니다. 물론 코딩은 지속적으로 할 수 있게 숙제가 나갈 예정입니다. - 정의정
4.6.2. 수업내용 ¶
- NTFS에 대하여 간략하게 설명하였습니다.
- 코 드 분 석
// 헤더 : ntfs.h #pragma once #define _WIN32_WINNT 0x0500 #include <windows.h> #include <winioctl.h> #include <stdio.h> typedef BOOLEAN TF; typedef UCHAR U8; typedef USHORT U16; typedef ULONG U32; typedef ULONGLONG U64; typedef struct { U32 Type; U16 UsaOffset; U16 UsaCount; U64 Usn; } NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER; typedef struct { NTFS_RECORD_HEADER Ntfs; U16 SequenceNumber; U16 LinkCount; U16 AttributeOffset; U16 Flags; // inUse 0x0001 Directory 0x0002 U32 BytesInUse; U32 BytesAllocated; U64 BaseFileRecord; U16 NextAttributeNumber; } FILE_RECORD_HEADR, *PFILE_RECORD_HEADER; // Standard Attribute typedef enum { AttributeStandardInformation = 0x10, AttributeAttributeList = 0x20, AttributeFileName = 0x30, AttributeObjectId = 0x40, AttributeSecurityDesciptor = 0x50, AttributeVolumeName = 0x60, AttributeVolumeInformation = 0x70, AttributeData = 0x80, AttributeIndexRoot = 0x90, AttributeIndexAllocation = 0xA0, AttributeBitmap = 0xB0, AttributeReparsePoint = 0xC0, AttributeEAInformation = 0xD0, AttributeEA = 0xE0, AttributePropertySet = 0xF0, AttributeLoggedUtilityStream = 0x100 } ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE; typedef struct { ATTRIBUTE_TYPE AttributeType; U32 Length; TF Nonresident; U8 NameLength; U16 NameOffset; U16 Flags; U16 AttributeNumber; } ATTRIBUTE, *PATTRIBUTE; typedef struct { ATTRIBUTE Attribute; U32 ValueLength; U16 ValueOffset; U16 Flags; } RESIDENT_ATTRIBUTE,*PRESIDENT_ATTRIBUTE; #pragma pack(push, 1) typedef struct { U8 Jump[3]; U8 Format[8]; U16 BytesPerSector; //섹터당 바이트 수 U8 SectorsPerCluster; //섹터당 클러스터수 U16 BootSectors; U8 Mbz1; U16 Mbz2; U16 Reserved1; U8 MediaType; U16 Mbz3; U16 SectorsPerTrack; U16 NumberOfHeads; U32 PartitionOffset; U32 Reserved2[2]; U64 TotalSectors; //디스크의 총 섹터수. U64 MftStartLcn; //MFT가 시작되는 주소. U64 Mft2StartLcn; // MFT Mirror 부분이 시작되는 주소 U32 ClustersPerFileRecord; // 파일 레코드당 클러스터수 U32 ClustersPerIndexBlock; // 인덱스 블럭당 클러스터수 U64 VolumeSerialNumber; U8 Code[0x1AE]; U16 BootSignature; } BOOT_BLOCK, *PBOOT_BLOCK; #pragma pack(pop)
- main.cpp
#include "ntfs.h" U32 BytesPerFileRecord; BOOT_BLOCK boot_block; HANDLE hVolume; U32 cnt; CHAR drive[] = "\\\\.\\C:"; PFILE_RECORD_HEADER MFT; void ReadSector(U64 sector, U32 count, void* buffer); void LoadMFT(); void main() { hVolume = CreateFile(drive, GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE, 0,OPEN_EXISTING, 0, 0); ReadFile(hVolume, &boot_block, sizeof(boot_block), &cnt, 0); printf("======My FILE SYSTEM INFO==========\n"); printf("File System : %s \n",boot_block.Format); printf("Total Sectors : %u \n",boot_block.TotalSectors); printf("Sector per Bytes : %u \n",boot_block.BytesPerSector); printf("Cluster per Sectors : %u\n",boot_block.SectorsPerCluster); printf("Clusters Per FileRecord : %u\n",boot_block.ClustersPerFileRecord); printf("Clusters Per IndexBlock : %u\n",boot_block.ClustersPerIndexBlock); } void LoadMFT() { BytesPerFileRecord = boot_block.ClustersPerFileRecord < 0x80? boot_block.ClustersPerFileRecord* boot_block.SectorsPerCluster* boot_block.BytesPerSector : 1 << (0x100 - boot_block.ClustersPerFileRecord); MFT = PFILE_RECORD_HEADER(new U8[BytesPerFileRecord]); ReadSector(boot_block.MftStartLcn * boot_block.SectorsPerCluster, BytesPerFileRecord / boot_block.BytesPerSector, MFT); printf("buffer : %s\n", MFT+0x27); } void ReadSector(U64 sector, U32 count, void* buffer) { ULARGE_INTEGER offset; OVERLAPPED overlap = {0}; U32 n; offset.QuadPart = sector * boot_block.BytesPerSector; overlap.Offset = offset.LowPart; overlap.OffsetHigh = offset.HighPart; ReadFile(hVolume, buffer, count * boot_block.BytesPerSector, &n, &overlap); }
4.6.3. 숙제 ¶
- http://forensic-proof.com/ 에서 mft에 대해 읽어보시오.
4.8.5. 후기 ¶
- CreateFile함수를 처음 사용하여보았습니다. - 김희성
참고 사이트
- 정의정선배께서 fopen으로 여는 것과 다를바가 없다고 하셔서 fopen으로 열고, fread로 읽어보았는데 결과가 같았습니다. - 김희성
- fopen의 경우 Standard함수인데 같은 input일 때, 리눅스에서 다르게 작동할지 궁금합니다. - 김희성
- 자료형별 16진법 자릿수가 헤깔리는군요. ;ㅅ; - 김희성
- 값을 확인하는데 이상한 값이 나와 검색해보니 MFT에서도 Little Endian형식을 쓰는 군요. - 김희성
- ReadFile의 overlap인자 사용법이 나와있는 곳을 찾기 힘듭니다 ;ㅅ;
ReadFile은 파일포인터를 읽은 만큼 옮기던데 ReadSector에서는 옮긴 지점부터 섹터 단위로 세어서 읽는 건가요? 아니면 처음부터 다시 세어 읽는건가요? - 김희성
- 함수를 반복해서 실행해 보았는데 읽는 위치가 같은 걸 보아, 파일 처음 부분부터 단위를 세는 것이군요. - 김희성
- 함수를 반복해서 실행해 보았는데 읽는 위치가 같은 걸 보아, 파일 처음 부분부터 단위를 세는 것이군요. - 김희성
- 파일 속성들을 읽는데 성공하였습니다.(2012/04/13/01:44)- 김희성
- 기타 참고 사이트
- CreateFile함수 사용시 문자열이 LPCWSTR로 변환되지 않는 문제가 생기는 경우에는 CreateFileA를 사용해보세요.
자세한 내용은 http://stackoverflow.com/questions/3783842/converting-a-string-to-lpcwstr-for-createfile-to-address-a-serial-port
4.9.2. 수업내용 ¶
#include "ntfs.h" U32 BytesPerFileRecord; BOOT_BLOCK boot_block; HANDLE hVolume; U32 cnt; CHAR drive[] = "\\\\.\\C:"; //WCHAR drive[] = TEXT("\\\\.\\C:"); PFILE_RECORD_HEADER MFT; void ReadSector(U64 sector, U32 count, void* buffer); void LoadMFT(); void main() { hVolume = CreateFile(drive, GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE, 0,OPEN_EXISTING, 0, 0); ReadFile(hVolume, &boot_block, sizeof(boot_block), &cnt, 0); // FILE *fp=fopen(drive,"rb"); // fread((void*)&boot_block,sizeof(boot_block),1,fp); printf("======My FILE SYSTEM INFO==========\n"); printf("File System : %s \n",boot_block.Format); printf("Total Sectors : %u \n",boot_block.TotalSectors); printf("Sector per Bytes : %u \n",boot_block.BytesPerSector); printf("Cluster per Sectors : %u\n",boot_block.SectorsPerCluster); printf("Clusters Per FileRecord : %u\n",boot_block.ClustersPerFileRecord); printf("Clusters Per IndexBlock : %u\n",boot_block.ClustersPerIndexBlock); printf("\n\n"); LoadMFT(); } void LoadMFT() { int i; BytesPerFileRecord = boot_block.ClustersPerFileRecord < 0x80? boot_block.ClustersPerFileRecord* boot_block.SectorsPerCluster* boot_block.BytesPerSector : 1 << (0x100 - boot_block.ClustersPerFileRecord); MFT = PFILE_RECORD_HEADER(new U8[BytesPerFileRecord]); ReadSector(boot_block.MftStartLcn * boot_block.SectorsPerCluster, BytesPerFileRecord / boot_block.BytesPerSector, MFT); printf("$MFT's Signaturer : %s\n", MFT);//+0x27); printf("Offset to fixup array : 0x%02x%02x\n", *((unsigned char*)MFT+5),*((unsigned char*)MFT+4)); printf("Number of this MFT Entry : 0x%02x%02x%02x%02x\n" , *((unsigned char*)MFT+47),*((unsigned char*)MFT+46),*((unsigned char*)MFT+45),*((unsigned char*)MFT+44)); printf("Offset to first attribute : 0x%02x%02x \n" , *((unsigned char*)MFT+21),*((unsigned char*)MFT+20)); i=((int)(*((unsigned char*)MFT+21))<<8)+*((unsigned char*)MFT+20);//Offset으로 포인터 이동 printf("First Attribute : 0x%02x%02x%02x%02x\n",*((unsigned char*)MFT+i+3),*((unsigned char*)MFT+i+2),*((unsigned char*)MFT+i+1),*((unsigned char*)MFT+i)); i+=4;//속성값의 4바이트 이동 printf("First Attribute Size : 0x%02x%02x%02x%02x\n",*((unsigned char*)MFT+i+3),*((unsigned char*)MFT+i+2),*((unsigned char*)MFT+i+1),*((unsigned char*)MFT+i)); printf("\n"); i= i+ ((int)(*((unsigned char*)MFT+i+3))<<24)+ ((int)(*((unsigned char*)MFT+i+2))<<16)+ ((int)(*((unsigned char*)MFT+i+1))<<8)+ *((unsigned char*)MFT+i) -4;//사이즈를 읽기위해 사용한 4바이트를 제외한다. printf("Second Attribute : 0x%02x%02x%02x%02x\n",*((unsigned char*)MFT+i+3),*((unsigned char*)MFT+i+2),*((unsigned char*)MFT+i+1),*((unsigned char*)MFT+i)); i+=4;//속성값의 4바이트 이동 printf("Second Attribute Size : 0x%02x%02x%02x%02x\n",*((unsigned char*)MFT+i+3),*((unsigned char*)MFT+i+2),*((unsigned char*)MFT+i+1),*((unsigned char*)MFT+i)); printf("\n"); i= i+ ((int)(*((unsigned char*)MFT+i+3))<<24)+ ((int)(*((unsigned char*)MFT+i+2))<<16)+ ((int)(*((unsigned char*)MFT+i+1))<<8)+ *((unsigned char*)MFT+i) -4;//사이즈를 읽기위해 사용한 4바이트를 제외한다. printf("Third Attribute : 0x%02x%02x%02x%02x\n",*((unsigned char*)MFT+i+3),*((unsigned char*)MFT+i+2),*((unsigned char*)MFT+i+1),*((unsigned char*)MFT+i)); i+=4;//속성값의 4바이트 이동 printf("Third Attribute Size : 0x%02x%02x%02x%02x\n",*((unsigned char*)MFT+i+3),*((unsigned char*)MFT+i+2),*((unsigned char*)MFT+i+1),*((unsigned char*)MFT+i)); printf("\n"); /* ReadSector(boot_block.Mft2StartLcn * boot_block.SectorsPerCluster, BytesPerFileRecord / boot_block.BytesPerSector, MFT); printf("$MFT Mirr's Signaturer : %s\n", MFT);//+0x27); printf("Offset to fixup array : 0x%02x%02x\n", *((unsigned char*)MFT+5),*((unsigned char*)MFT+4)); printf("Number of this MFT Entry : 0x%02x%02x%02x%02x\n" , *((unsigned char*)MFT+47),*((unsigned char*)MFT+46),*((unsigned char*)MFT+45),*((unsigned char*)MFT+44)); printf("\n"); //*/ printf("MftStartLcn : %d\n",boot_block.MftStartLcn); printf("Mft2StartLcn : %d\n",boot_block.Mft2StartLcn); } void ReadSector(U64 sector, U32 count, void* buffer) { ULARGE_INTEGER offset; OVERLAPPED overlap = {0}; U32 n; offset.QuadPart = sector * boot_block.BytesPerSector; overlap.Offset = offset.LowPart; overlap.OffsetHigh = offset.HighPart; ReadFile(hVolume, buffer, count * boot_block.BytesPerSector, &n, &overlap); }
4.9.5. 후기 ¶
- 뒤집어 읽는 함수는 없고, 리틀엔디언을 빅엔디언으로 변환하는 함수는 있군요.
소캣 라이브러리를 요구합니다.
htons, htonl
- HxD라는 헥스에디터가 있습니다. 4기가 바이트이상의 파일을 열수 있고 최대 8엑사 바이트까지 열 수 있다고 합니다. 그리고 가장 중요한 건 프리웨어네요.
http://mh-nexus.de/en/hxd/ - 권영기
- Code jam으로 불태웠더니 시간이... - 김희성
- 공간을 절약해야하는 저장이라 자료형이 일정하지않습니다. 4bit unsigned 정수형부터 3byte,7byte unsigned 정수형까지 상상을 초월하네요.ㅠㅜ - 김희성
4.10.2. 수업내용 ¶
#include "ntfs.h" U32 BytesPerFileRecord; BOOT_BLOCK boot_block; HANDLE hVolume; U32 cnt; CHAR drive[] = "\\\\.\\C:"; //WCHAR drive[] = TEXT("\\\\.\\C:"); PFILE_RECORD_HEADER MFT; void ReadSector(U64 sector, U32 count, void* buffer); void LoadMFT(); unsigned int LoadAttribute(int i); unsigned __int64 htonll(unsigned __int64); unsigned int htonl(unsigned int); //unsigned short htons(unsigned short); void main() { hVolume = CreateFile(drive, GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE, 0,OPEN_EXISTING, 0, 0); ReadFile(hVolume, &boot_block, sizeof(boot_block), &cnt, 0); // FILE *fp=fopen(drive,"rb"); // fread((void*)&boot_block,sizeof(boot_block),1,fp); printf("======My FILE SYSTEM INFO==========\n"); printf("File System : %s \n",boot_block.Format); printf("Total Sectors : %u \n",boot_block.TotalSectors); printf("Sector per Bytes : %u \n",boot_block.BytesPerSector); printf("Cluster per Sectors : %u\n",boot_block.SectorsPerCluster); printf("Clusters Per FileRecord : %u\n",boot_block.ClustersPerFileRecord); printf("Clusters Per IndexBlock : %u\n",boot_block.ClustersPerIndexBlock); printf("\n\n"); LoadMFT(); system("pause"); } void LoadMFT() { int point; unsigned __int64 num; BytesPerFileRecord = boot_block.ClustersPerFileRecord < 0x80? boot_block.ClustersPerFileRecord* boot_block.SectorsPerCluster* boot_block.BytesPerSector : 1 << (0x100 - boot_block.ClustersPerFileRecord); MFT = PFILE_RECORD_HEADER(new U8[BytesPerFileRecord]); printf("MftStartLcn : %016x\n",boot_block.MftStartLcn); printf("Mft2StartLcn : %016x\n",boot_block.Mft2StartLcn); printf("\n"); //0 대신 값을 대입하면 다른 MFT entry를 볼 수 있음. ReadSector((boot_block.MftStartLcn+0) * boot_block.SectorsPerCluster, BytesPerFileRecord / boot_block.BytesPerSector, MFT); printf("MFT's Signaturer : %s\n", MFT);//+0x27); printf("Offset to fixup array : 0x%02x%02x\n", *((unsigned char*)MFT+5),*((unsigned char*)MFT+4)); printf("Number of this MFT Entry : 0x%02x%02x%02x%02x\n" , *((unsigned char*)MFT+47),*((unsigned char*)MFT+46),*((unsigned char*)MFT+45),*((unsigned char*)MFT+44)); printf("Offset to first attribute : 0x%02x%02x \n" , *((unsigned char*)MFT+21),*((unsigned char*)MFT+20)); printf("\n"); point=((int)(*((unsigned char*)MFT+21))<<8)+*((unsigned char*)MFT+20);//Offset으로 포인터 이동 printf("Attribute List Start\n\n"); while(htonl(*((unsigned int*)((unsigned char*)MFT+point)))!=0xFFFFFFFF) point+=LoadAttribute(point); printf("Attribute List End\n"); printf("\n"); } unsigned int LoadAttribute(int point) { int i=0,j=0,k=0; int HeaderSize; /* *((unsigned char*)MFT+i+9) = Attribute Name Size Resident=24 / Non-resident=64 */ if(*((unsigned char*)MFT+point+8)) HeaderSize=64+*((unsigned char*)MFT+point+9); else HeaderSize=24+*((unsigned char*)MFT+point+9); switch(htonl(*((unsigned int*)((unsigned char*)MFT+point)))) { case 0x10://$STANDARD_INFORMATION printf("Attribute type : Standard Information\n"); break; case 0x20://$ATTRIBUTE_LIST printf("Attribute type : Attribute List\n"); break; case 0x30://$FILE_NAME printf("Attribute type : File Name\n"); printf("File Name Size : %d\n",*((unsigned char*)MFT+point+HeaderSize+64)); printf("File NameSpace : "); switch(*((unsigned char*)MFT+point+HeaderSize+65)) { case 0: printf("POSIX\n"); break; case 1: printf("Win32\n"); break; case 2: printf("DOS\n"); break; case 3: printf("Win32 & DOS\n"); break; } printf("File Name : "); for(j=0;j<2**((unsigned char*)MFT+point+HeaderSize+64);j++) printf("%c",*((unsigned char*)MFT+point+HeaderSize+66+j)); printf("\n"); break; case 0x40://$ printf("Attribute type : \n"); break; case 0x50://$SECURITY_DESCRIPTOR printf("Attribute type : Security Descriptor\n"); break; case 0x60://$ printf("Attribute type : \n"); break; case 0x70://$ printf("Attribute type : \n"); break; case 0x80://$DATA printf("Attribute type : Data\n"); //__int64는 메모리상에 little endian식으로 저장됨. 왜인지 이해가 안 가지만... printf("Run List Start VCN : %I64d\n",*((unsigned __int64*)((unsigned char*)MFT+point+16))); printf("Run List End VCN : %I64d\n",*((unsigned __int64*)((unsigned char*)MFT+point+24))); printf("Run List Start Offset : 0x%02x%02x\n",*((unsigned char*)MFT+point+33),*((unsigned char*)MFT+point+32)); // printf("Cluster Size : %I64d\n",*((unsigned __int64*)((unsigned char*)MFT+point+40))); // printf("Attribute Size : %I64d\n",*((unsigned __int64*)((unsigned char*)MFT+point+48))); // printf("real Size : %I64d\n",*((unsigned __int64*)((unsigned char*)MFT+point+56))); i=(int)*((unsigned char*)MFT+point+33)+*((unsigned char*)MFT+point+32); for(j=0;j<(*((unsigned char*)MFT+point+i)&0x0F);j++)//*((unsigned __int64*)((unsigned char*)MFT+point+24));j++) { printf("Cluster %d lenth : 0x",j); for(k=0;k<(*((unsigned char*)MFT+point+i)&0x0F);k++) printf("%02x",*((unsigned char*)MFT+point+i+(*((unsigned char*)MFT+point+i)&0x0F)-k)); printf("\n"); printf("Cluster %d offset : 0x",j); for(;k<(*((unsigned char*)MFT+point+i)&0x0F)+((*((unsigned char*)MFT+point+i)&0xF0)>>4);k++) printf("%02x",*((unsigned char*)MFT+point+i +(*((unsigned char*)MFT+point+i)&0x0F)+((*((unsigned char*)MFT+point+i)&0xF0)>>4) -k+(*((unsigned char*)MFT+point+i)&0x0F))); printf("\n"); i+=(*((unsigned char*)MFT+point+i)&0x0F)+((*((unsigned char*)MFT+point+i)&0xF0)>>4)+1; } break; case 0xB0: printf("Attribute type : Bitmap\n"); break; } printf("\n"); return htonl(*((unsigned int*)((unsigned char*)MFT+point+4))); } void ReadSector(U64 sector, U32 count, void* buffer) { ULARGE_INTEGER offset; OVERLAPPED overlap = {0}; U32 n; offset.QuadPart = sector * boot_block.BytesPerSector; overlap.Offset = offset.LowPart; overlap.OffsetHigh = offset.HighPart; ReadFile(hVolume, buffer, count * boot_block.BytesPerSector, &n, &overlap); } unsigned __int64 htonll(unsigned __int64 LittleEndian) { unsigned __int64 BigEndian; int i; LittleEndian>>=16; BigEndian=0; BigEndian+=(unsigned __int64)(*((unsigned char*)&LittleEndian+7))<<54; BigEndian+=(unsigned __int64)(*((unsigned char*)&LittleEndian+6))<<48; BigEndian+=(unsigned __int64)(*((unsigned char*)&LittleEndian+5))<<40; BigEndian+=(unsigned __int64)(*((unsigned char*)&LittleEndian+4))<<32; BigEndian+=(unsigned __int64)(*((unsigned char*)&LittleEndian+3))<<24; BigEndian+=(unsigned __int64)(*((unsigned char*)&LittleEndian+2))<<16; BigEndian+=(unsigned __int64)(*((unsigned char*)&LittleEndian+1))<<8; BigEndian+=(unsigned __int64)(*((unsigned char*)&LittleEndian+0)); return BigEndian; } unsigned int htonl(unsigned int LittleEndian) { unsigned int BigEndian; BigEndian= ((unsigned int)(*((unsigned char*)&LittleEndian+3))<<24)+ ((unsigned int)(*((unsigned char*)&LittleEndian+2))<<16)+ ((unsigned int)(*((unsigned char*)&LittleEndian+1))<<8)+ *((unsigned char*)&LittleEndian) ; return BigEndian; } /* unsigned short htons(unsigned short LittleEndian) { unsigned short BigEndian; BigEndian= ((unsigned short)(*((unsigned char*)&LittleEndian+1))<<8)+ *((unsigned char*)&LittleEndian) ; return BigEndian; } /*/
4.10.5. 후기 ¶
- 타임스탬프에서 멘붕, 이 파트는 그냥 영기한테 넘길까 고민 중...- 김희성
- (이보시오 MS 양반, 시간이 micro second 단위라니)
- (이보시오 MS 양반, 시간이 micro second 단위라니)
- http://ezbeat.tistory.com/124
타임스탬프 포멧 변환 API - 김희성
- http://lioler.blog.me/20051109234
NFTS 설명 - 김희성
- 작업 현황
클래스화 중, 읽을 수 있는 속성을 늘리는 중. (현재 기본 정보, 파일 이름, data 영역 읽기 가능)
김희성/MTFREADER - 김희성