2010년 6월 9일 수요일

apache 설치하기 (CentOS)

운영체제를 깔때 서버 버전으로 깔아서 기본적으로 Httpd 가 설치되어 있었다.

하지만 내가 복사해야될 폴더며 내가 필요한 것들은 당췌 어디 있는지... 알 수가 없었다 ;;;

그래서 과감히 소프트웨어 추가 삭제에서 삭제를 하고, 다운 받아서 다시 깔았다.

http://www.apache.org  에서 Linux 용 최신 버전 다운


1. tar 파일의 압축을 푼다.

# tar xvf httpd-2.2.13.tar


2. 컴파일 스크립트 수행

# ./configure --with-layout=apache --prefix-/usr/local/web/apache --enable-module=so --enable-mods-shared=all --enable-so -enable-rewrite

prefix = 설치 경로
--enable-module=so 는 tomcat 연동이나 다른 연동시 필요하므로 꼭 추가.
여기서
configure: error: no acceptable C compiler found in $PATH
이런 에러가 뜬다면 gcc 가 깔려 있는지 확인하자.
# rpm -qa | grep gcc

없다면.
# yum install gcc

mod_deflate has been requested but can not be built due to prerequisite failures
에러가 난다면.

# yum -y install zlib-devel

뭐 대략적으로 설치가 안되서 나는 에러다.

3. 컴파일

# make


4. install

# make install


에러 없이 설치가 되었다면 성공.


부팅시 자동으로 띄우고 싶다면.


#cp /usr/local/web/apachectl /etc/init.d/httpd

#vi /etc/init.d/httpd


#!bin/sh 밑에 아래 내용을 넣는다.
#chkconfig: 2345 90 90
#processname: /usr/local/web/apache/bin/apachectl
#config: /usr/local/web/apache/conf/httpd.conf
#pidfile: /usr/local/web/apache/logs/httpd.conf


저장.

#chkconfig --add httpd
#chkconfig --list httpd


하면 httpd 가 있는지 확인.

# ntsysv

하면 파란 화면이 뜬다.
여기서 httpd 에 * 가 쳐져 있다면 자동 실행된다.

#service httpd start


하고

http://localhost

들어가면

It works!

라고 뜬다.

2010년 5월 15일 토요일

iphone sdk 언인스톨

sudo /Developer/Library/uninstall-devtools --mode=all

2010년 5월 14일 금요일

디스크 초기화

clearhdd 1 타이핑후 y를 선택한다음 재부팅 하면 된다.

 

mbr(master boot record) 을삭제해야한다.

MBR은 파티션 위치정보를 가지고 있다.그리고 운영체제가 저장되어있는 파티션의 부트섹터를

읽어올수있는 프로그램을 포함하고 있다.

부트섹터에는 OS를 메모리에 올릴수있는 프로그램이 내장되어 있다

 

FDISK 는 파티션을 나누는 즉 디스크영역을 만드는 것이고

FDISK /mbr 은 mbr영역까지 삭제하는 명령이다.

 

실제로 Fdisk/mbr은 mbr영역중 파티션테이블 64byte를 제외한 나머지 mbr영역을 fdisk가 다시

기록해주는 것이다.

파티션테이블을 제외한 mbr영역이 손상되었을때 복구하는 도구로 사용된다.

파티션테이블 손상시에는 다른 복구유틸이나 백업본을 이용해야한다.

 

 

2010년 5월 13일 목요일

해킨토시 설치하기

The first time I installed OSX on my P1610 I used Kalyway 10.5.2, it was pretty successful,
but there were a few remaining issues and it was a lot of hard work.
Quite a few months down the line and much has improved in the world of hackintosh,
My latest install is with iAtkos v7, which can be found at any good torrent search.

I do suggest burning the disc at the slowest speed possible to minimise errors on the DVDR.
Here is how I installed iAtkos v7 OS X 10.5.7 on my Fujitsu P1610.
I'm not guaranteeing it will work for you, it's just how I did it.

MANY MANY THANKS to all that put the work in to make this possible.


<Preparation>
-------------
The very first thing I did was replace the standard Atheros WiFi card in my P1610,
with a Airport compatible 802.11N Broadcom based WiFi card, that I picked up off eBay.
No idea if iAtkos v7 supports the original Atheros card as I got rid of ages ago.

Downloaded and burned the iAtkos v7 disc image at x2 speed.

Plug in my external USB DVD rom and put the iAtkos v7 disc in.
Turn on your Fujitsu Lifebook P1610 and at the POST screen hit F2 to enter the BIOS.
In the BIOS go over to Boot and down to Boot Device Priority.
in the list of Boot priority order, I removed everything except CD/DVD drive,
hit x to remove or add a device to the list.
Hit F10 to save and exit, then enter to confirm.


<Installation>
--------------
Boot from CD/DVD drive and at the Darwin loader
press F8 for options and type -v to boot in verbose mode.
Once the installer loads up
click the button to continue

under utilities menu
click on Disk Utility

Select the drive in your P1610, then choose the Partition tab.
You could create just one partition if you want just Mac OS X, format it in Mac OS Extended (Journaled) format.

----
I have mine setup as a dualboot, Mac OS X and Windows XP Tablet.
So created two equal sized paritions the first being a Mac OS Extended (Journaled)
the second being (MS-DOS) FAT so I can install Windows XP Tablet to it.
Once the partitions are created,
I then install Windows XP Tablet as I normally would, during the XP installation I reformat the FAT partition to NTFS.
Since it doesn't see the Mac OS Extended (Journaled) partition there is no issues here.
After installing Windows XP, boot from the iAtkos disc again with F8 and typing -v.
----

Agree to the edited iAtkos license agreement,
Select a Destination - click on the Mac OS partiton, then continue
Install Summary - Customize
(the following are the options I used, they may not be the best, but they work for me.)

-iATKOS v7 Main System

-Bootloader
--Chameleon v2

-X86 Patches
--/Extra directory
--DSDT
--Decrypters
---AppleDecrypt
--SMBIOS drivers
---SMBIOS Enablers
----SMBIOS Resolver
---SMBIOS' for X86
----AppleSMBIOS-28
--Kernel
---9.7.0 Kernel voodoo
--Disabler

-Drivers
--VGA
---Intel
----GMA 950
-----GMA 950 Laptop
--System
---SATA/IDE
----Generic IDE
---CardBus Driver
---USB
---Sound
----Voodoo HDA driver
---PS/2 mouse/keyboard
----Apple PS/2 driver
---Laptop Battery
---NTFS-3G
---Network
----Wireless
-----Broadcom BCM43xx

-Post-Install Actions


Click Done, then Install


<Setup>
-------
Once the Install has succeeded, click restart,
and when you get the Fujitsu POST screen hit F2 to go into the BIOS
Unplug the USB DVD drive
Remove the CD/DVD drive from the Boot priority order,
and re-add the hard drive Drive0:
Press F10 to save and exit, then enter to confirm.
When you get the Chameleon boot screen, push down three times to select Boot Verbose and hit enter.

OSX will start up and you should hear some funky music playing out the speakers,

Select Country
Keyboard
Dou you already own a mac? - Continue
Select a wireless Service
Enter your Apple ID - you can leave it blank and hit Continue
Registration Information - Alt+Q to skip
Create Your Account Name and a password
Select Time Zone
Set the Date and Time
Don't Forget to Register - Done


<Display> 반드시 설정해야한다 .
---------
First things first, set the correct screen resolution.
Click on System preferences, the metallic looking Cogs icon at the bottom
then under the Hardware heading, Displays.
select 1280x768 to get the correct resolution.

/Library/Preferences/SystemConfiguration/com.apple.Boot.plist 에서

<key>Graphic Mode</key>

<string>1280*768*32</string>

를 입력후 저장 한다 맨 아래쪽에

만약 하지 않게 되면 재부팅 했을경우 gui를 볼수 없게 된다.



<Ethernet Networking>
---------------------
1. 터미널 실행
2. sudo -s 실행(관리자 권한 획득)
3. 관리자 암호 입력
4. vi /System/Library/Extensions/IONetworkingFamily.kext/Contents/Plugins/AppleYukon2.kext/Contents

/Info.plist

아래 색칠된 부분 수정

<key>Yukon-88E8055</key>
        <dict>
            <key>CFBundleIdentifier</key>
            <string>com.apple.iokit.AppleYukon2</string>
            <key>EnableLowPwr</key>
            <integer>1</integer>
            <key>IOClass</key>
            <string>yukon2osx</string>
            <key>IOPCIPrimaryMatch</key>
            <string>0x436311ab</string>
            <key>IOPCISecondaryMatch</key>
            <string>0x139a10cf</string>
            <key>IOProviderClass</key>
            <string>IOPCIDevice</string>
            <key>InitialWaitForLinkUp</key>
            <string></string>
            <key>MACNumber</key>
            <integer>1</integer>
            <key>Model</key>
            <string>Yukon Gigabit Adapter 88E8055 Singleport Copper SA</string>
            <key>NetworkNumber</key>
            <integer>6000</integer>
            <key>Vendor</key>
            <string>marvell</string>
        </dict>


5. rm /System/Library/Extensions.mkext
6. diskutil repairPermissions /
7. reboot


<Keyboard layout>
-----------------
http://www.insanelymac.com/forum/index.php...st&p=767201
download and install the Microsoft Keyboard layouts,
once that's done, restart the computer and go into System Preferences and select International.
Select Input Menu.
scroll through and check the box for the keyboard you have.
mine is British - Microsoft.
Then up in the top right you'll see a little Flag where you can click on to change the keyboard layout.


<Upgrade to 10.5.8>
-------------------
Click on the Apple icon, top right, and select Software update,
uncheck the 10.5.8 update for now, and update everything else.
once it's all updated and restarted, check for updates again,
hopefully there is now only the 10.5.8 update left.
Check that and apply that update, it takes a while,
but it should restart a couple of times and you'll now have 10.5.8 running on your P1610.


<Things that are not working>
-----------------------------
Touchscreen, Buttons on the screen bezel, SD card reader.
I don't think I'm going to be able to get the Touchscreen to work,
as the P1610 uses a serial touchscreen controller, which there doesn't seem to be any support for.
Again the same for the buttons on the screen bezel, no support.
But I reckon with a bit more hunting around I should be able to get the SD card reader working. Hopefully.

2010년 5월 7일 금요일

파일을 DB처럼 사용하는법

class CInfo
{
public:
char szName[40];
char szPhone[40];
char szMobile[40];
char szAddress[40];
char szEmail[40];
char szEtc[1024-40*5-7];
char szn[3];


CInfo(){
  memset(szName, 0 ,sizeof(char)*40);
  memset(szPhone, 0 ,sizeof(char)*40);
  memset(szMobile, 0 ,sizeof(char)*40);
  memset(szAddress, 0 ,sizeof(char)*40);
  memset(szEmail, 0 ,sizeof(char)*40);
  memset(szEtc, 0 ,sizeof(char)*1024-40*5-7);
  memset(szn,0,sizeof(szn));
  strncpy(szn,_T("\r\n"),sizeof("\r\n"));
}
};

1.데이터 삽입(Insert)



void CFileDB::InsertInFile(CInfo &Info)
{


m_hFile = CreateFile(_T("c:\\test001.dat"), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

DWORD nWrite = 0;

SetFilePointer(m_hFile,0,NULL,FILE_END);

//WriteFile(m_hFile,_T("\n"),sizeof("\n"),&nWrite,NULL);




if(m_hFile != INVALID_HANDLE_VALUE)
{
  WriteFile(m_hFile,&Info,sizeof(Info),&nWrite,NULL);
}

CloseHandle(m_hFile);


}



2.데이터 조회(Select)



void CFileDB::SelectInFile(void)
{

UpdateData(TRUE);


DWORD dwStartTime, dwFinishTime;
CInfo Info;
memset(&Info,0,sizeof(Info));



m_hFile = CreateFile(_T("c:\\test001.dat"), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

SetFilePointer(m_hFile,0,NULL,FILE_BEGIN);

int nNumOfData = GetFileSize(m_hFile,NULL)/sizeof(CInfo);

DWORD nRead = 0;

if(m_hFile != INVALID_HANDLE_VALUE)
{
  for(int i = 0 ; i< nNumOfData ; ++i)
  {
   SetFilePointer(m_hFile,sizeof(Info)*i,NULL,FILE_BEGIN);
   ReadFile(m_hFile,&Info,sizeof(Info),&nRead,NULL);

   if(m_strNameSearch.Compare(Info.szName) == 0 )
   {
    // 데이타를 표시한다.
    m_uIndex = i;
    m_strName = Info.szName;
    m_strPhone = Info.szPhone;
    m_strMobile = Info.szMobile;
    m_strAddress = Info.szAddress;
    m_strEmail = Info.szEmail;
    dwFinishTime = GetTickCount();
    m_uTime = 0;

   }
  }
 
}

CloseHandle(m_hFile);

UpdateData(FALSE);

}



3.데이터 수정(Update)



void CFileDB::UpdateInFile(void)
{

UpdateData(TRUE);


DWORD dwStartTime, dwFinishTime;
CInfo Info;
memset(&Info,0,sizeof(Info));

m_hFile = CreateFile(_T("c:\\test001.dat"), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

SetFilePointer(m_hFile,0,NULL,FILE_BEGIN);

int nNumOfData = GetFileSize(m_hFile,NULL)/sizeof(CInfo);

DWORD nRead = 0;
DWORD nWrite = 0;

if(m_hFile != INVALID_HANDLE_VALUE)
{
  for(int i = 0 ; i< nNumOfData ; ++i)
  {
   SetFilePointer(m_hFile,sizeof(Info)*i,NULL,FILE_BEGIN);
   ReadFile(m_hFile,&Info,sizeof(Info),&nRead,NULL);

   if(m_strNameSearch.Compare(Info.szName) == 0 )
   {
    // 데이타를 표시한다.
    m_uIndex = i;
    strncpy(Info.szName,m_strName,strlen(m_strName));
    strncpy(Info.szPhone, m_strPhone,strlen(m_strPhone));
    strncpy(Info.szMobile, m_strMobile,strlen(m_strMobile));
    strncpy(Info.szAddress, m_strAddress,strlen(m_strAddress));
    strncpy(Info.szEmail, m_strEmail,strlen(m_strEmail));
    dwFinishTime = GetTickCount();
    m_uTime = 0;

    SetFilePointer(m_hFile,sizeof(Info)*i,NULL,FILE_BEGIN);
    WriteFile(m_hFile,&Info,sizeof(Info),&nWrite,NULL);

    MessageBox(_T("수정이 완료되었습니다."));

   }
  }

}

CloseHandle(m_hFile);

UpdateData(FALSE);

}



4.데이터 삭제(Delete)

void CFileDB::DeleteInFile(void)
{
CInfo Info;
DWORD nRead = 0;
DWORD nWrite = 0;

BOOL bCompare = FALSE;


m_hFile = CreateFile(_T("c:\\test001.dat"), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
SetFilePointer(m_hFile,0,NULL,FILE_BEGIN);

int nNumOfData = GetFileSize(m_hFile,NULL)/sizeof(CInfo);

if(m_hFile != INVALID_HANDLE_VALUE)
{
  for(int i = 0 ; i< nNumOfData ; ++i)
  {
   SetFilePointer(m_hFile,sizeof(Info)*i,NULL,FILE_BEGIN);
   ReadFile(m_hFile,&Info,sizeof(Info),&nRead,NULL);

   if(m_strName.Compare(Info.szName) == 0 )
   {
    bCompare = TRUE;
   
   }

   if(bCompare)
   {
    //바로 뒤에 있는 데이터를 읽어서
    SetFilePointer(m_hFile,sizeof(Info)*(i+1),NULL,FILE_BEGIN);
    ReadFile(m_hFile,&Info,sizeof(Info),&nRead,NULL);
    //데이터를 삭제한 곳에 덮어쓴다.
    SetFilePointer(m_hFile,sizeof(Info)*i,NULL,FILE_BEGIN);
    WriteFile(m_hFile,&Info,sizeof(Info),&nWrite,NULL);  

   }


  }
}

if(bCompare)
{
  CInfo blank;
  memset(&blank,0,sizeof(CInfo));
  SetFilePointer(m_hFile,sizeof(CInfo)*(nNumOfData -1),NULL,FILE_BEGIN);
  WriteFile(m_hFile,&blank,sizeof(blank),&nWrite,NULL);

  MessageBox(_T("삭제가 완료되었습니다."));

}

CloseHandle(m_hFile);

}

2010년 4월 27일 화요일

프로세스감추기 2

이번엔 프로세스를 숨기는 방법에 대해 말씀드리려고 합니다.

윈도우에는 유저영역과 커널영역이 있습니다.

SDK를 이용해서 만들어지는 모든 응용 프로그램은 유저 영역에서만

다루어집니다.

아니, 윈도우에서는 응용 프로그램이 커널 영역을 건드리는 것을 막아 놓았습니다.

사실, 핸들이라는 것을 통해서 응용 프로그램은 간접적으로 커널 영역을 건드리는데요,

커널을 만지지 않고서는 아무 작업도 할 수 없기 때문에

윈도우가 고안한 방법일 겁니다.

커널을 직접 건드리기 위해선 DDK라는 것을 통해 시스템 프로그램 내지는

드라이버(확장자가 .sys입니다)를 만드는게 보통인데요,

제가 설명하고자 하는 방법은 SDK만을 이용한 방법입니다.

프로세스를 숨기는 기본적인 원리는 이렇습니다.

윈도우에는 커널영역이 있다고 했죠?

그리고 그 영역에 접근하기 위한 핸들이 있다고 했습니다.

각각의 핸들에는 대응되는 오브젝트가 있습니다.

예를 들어 윈도우 핸들에는 윈도우 정보를 담고 있는 구조체가,

프로세스 핸들에는 프로세스 정보를 담고 있는 구조체가 있습니다.

이 프로세스의 정보를 담은 구조체의 이름은 EPROCESS입니다.

EPROCESS에는 엄청나게 많은 멤버가 있는데요, 그 중 이 테마에 중요한 것은

ActiveProcessLinks라는 멤버 하나 뿐입니다.

이름에서 대략 눈치채셨겠지만, 프로세스들은 연결리스트 구조로 연결되어있습니다.

때문에 목표하는 프로세스를 연결리스트에서 끊기만 하면 감쪽같이

목록에서 사라지게 되지요.

혹시 CPU 사용 권한을 잃게 될 까 걱정하지 않아도 됩니다. 왜냐면,

작업은 쓰레드를 기반으로 이루어지기 때문에, 프로세스는 이름일 뿐입니다.

윈도우즈의 버전에 따라 ActiveProcessLinks의 오프셋값이 다른데요,

XP의 경우 구조체의 시작 번지로 부터 0x088만큼 떨어진(오프셋된) 위치에

ActiveProcessLinks가 있습니다. 이 멤버의 자료형은 LIST_ENTRY인데, 이는

SDK플랫폼에도 정의가 되어있는 구조체로, 다음 두 멤버를 가집니다.

PLIST_ENTRY Flink;
PLIST_ENTRY Blink;

그러므로,
ActiveProcessLinks.Filnk->Blink = ActiveProcessLinks.Blink;
ActiveProcessLinks.Bilnk->Flink = ActiveProcessLinks.Flink;
의 작업을 거쳐주면 되는 겁니다.

그럼 문제는 EPROCESS의 주소를 어떻게 알아내는가 인데요..

바로 여기에 여러가지 테크닉이 존재합니다.

어떤 방법을 사용하든지 Native API를 사용하게 될 텐데요,

이는 SDK에 정의되어있지 않으므로, GetProcAddress를 통해 직접 주소를 얻어내야 합니다.

제가 설명할 방법에 쓰이는 API함수는 다음 두 개입니다.

NTSTATUS __stdcall ZwQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL );

NTSTATUS __stdcall ZwSystemDebugControl(IN SYSDBG_COMMAND SysDbgChunks, IN OUT PVOID pQueryBuff, DWORD dwSize, DWORD, DWORD, NTSTATUS *pResult);

NTSTATUS는 DDK에서 쓰이는 자료형으로, SDK에서 사용하려면 LONG형을 typedef해야 합니다.

(아시는 분은 알겠지만, 참고로 예기해 드립니다. IN, OUT, OPTIONAL은 아무 의미없는 #define으로, 인자가 입력인지, 출력인지, 그리고 사용하지 않으므로 NULL을 넣어도 되는가 등을 예기해주는 겁니다)

SYSTEM_INFORMATION_CLASS 는 enum으로 정의된 자료형으로, 여러가지 값이

정의되어 있습니다. 어떤 분이 찾아내셨는지는 모르겠지만;;

그 목록에 나와있지 않은 값들 중에서 16을 넣게 되면, 재미있는 일이 벌어지는데요,

이걸 이용할 것입니다. 사용할 값은 16뿐이므로 SYSTEM_INFORMATION_CLASS를

다음과 같이 정의해서 사용하면 됩니다.

typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemHandleInformation = 16
} SYSTEM_INFORMATION_CLASS;

너무 길어지네요;; 2부에서 계속합니다.

 

 

SystemHandleInformation이란 이름에서 알 수 있듯,

16은 시스템 상에 로드되어있는 모든 핸들에 대한 정보를 얻어오게 합니다.

그 정보는 다음과 같은 구조체의 배열에 저장됩니다.

typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

눈여겨 보아야 할 것은 첫번째, 두번째, 다섯번째 인자인데요,

첫번째 인자는 이 핸들을 소유한 프로세스의 아이디입니다. 두번째 인자는

이 핸들의 타입인데요, 핸들에는 여러 종류가 있으니 이를 구분해 주는 겁니다.

윈도우 핸들, 쓰레드 핸들 등 많은 종류가 있지만, 프로세스는 5번입니다.

즉, 이 핸들이 우리가 찾고자 하는 프로세스인지 아닌지 조사하려면,

우선 첫번째 인자와 찾고자 하는 프로세스의 아이디를 조사하고,

두번째 인자가 5인지를 조사하면 되는 겁니다.

그리고 대망의 다섯번째 인자는 바로 EPROCESS구조체의 주소입니다.

이제 ZwQuerySystemInformation의 각 인자에 대해 설명드리겠습니다.

첫번째 인자는 어떤 종류의 정보를 얻어올 것인가로, 16을 입력할 경우 시스템 핸들 정보를

얻어온다고 했습니다.

두번째 인자는 정보를 입력받을 버퍼의 포인터입니다.

세번째 인자는 버퍼의 크기입니다.

네번째 인자는 정보의 크기입니다.

시스템 상에 핸들이 얼마나 많은지 모르기 때문에, 적당한 버퍼의 크기를 알 수가 없습니다.

그래서 1바이트 부터 시작해서 계속 2씩 곱해가면서 적당한 사이즈를 찾는데요,

버퍼의 크기가 부적절한 경우 ZwQuerySystemInformation은

STATUS_INFO_LENGTH_MISMATCH라는 값을 반환합니다.

이 값 역시 DDK에서 사용하는 매크로로, ((NTSTATUS)0xC0000004L)와 같이 정의하면 됩니다.

사이즈가 적당치 않은 경우는 버퍼를 free하고 크기를 두배로 늘린 뒤 다시 시도하는

반복문을 돌려서, 적당한 크기를 찾습니다.

크기가 충분해서 Query Information이 성공하면,

ZwQuerySystemInformation은 0이상의 값을 반환합니다.

네번째 인자는 OPTIONAL이므로 그냥 0을 주면 됩니다.

아무튼 이렇게 해서 얻어낸 정보의 앞 4바이트는 배열의 인자 개수를 나타냅니다.

다시말하면 시스템상에 존재하는 핸들의 숫자입니다.

이제 이 숫자만큼 루프를 돌면서 원하는 핸들을 찾아내면 됩니다.

헥헥.; 여기까지가 EPROCESS의 주소를 알아내는 방법입니다.

이제 다 끝난게 아닌가 하시겠지만, 사실 더 있습니다.

이렇게 얻어낸 EPROCESS의 주소는 선형 주소라는 것으로, 직접 접근할 수가 없습니다.

주소에는 물리 주소, 선형 주소, 논리 주소 이렇게 3개가 있는데요,

보통 그냥 사용해 왔던 포인터 변수는 논리 주소입니다.

선형 주소는 가상 주소라고도 하는데요, ZwSystemDebugControl은 여기서 쓰입니다.

이녀석도 첫번째 인자로 enum자료형을 받는데요, 여기서 사용할 값은

8, 9 두 개이므로, 다음과같이 정의해서 쓰면 됩니다.

typedef enum _SYSDBG_COMMAND
{
SysDbgCopyMemoryChunks_0 = 0x08, SysDbgCopyMemoryChunks_1 = 0x09
} SYSDBG_COMMAND;

두번째 인자는 데이터를 받을 구조체의 포인터입니다.

이 구조체는 MEMORY_CHUNKS라는 구조체로, 다음과 같이 정의됩니다.

typedef struct _MEMORY_CHUNKS
{
PVOID pVirtualAddress;
PVOID pBuffer;
DWORD dwBufferSize;
} MEMORY_CHUNKS, *PMEMORY_CHUNKS;

첫번째 멤버로 접근하고자 하는 메모리의 주소를 입력하고,

두번째 멤버와 세번째 멤버에 데이터를 저장할 버퍼의 주소와 그 크기를 입력합니다.

가상메모리를 읽는 경우(SysDbgCopyMemoryChunks_0),

이 버퍼로 가상 메모리의 데이터가 쓰여집니다.

가상메모리를 쓰는 경우(SysDbgCopyMemoryChunks_1),

이 버퍼에 쓰인 내용이 가상 메모리에 쓰여집니다.

한편 ZwSystemDebugControl의 세번째 인자는 읽고자 하는 데이터의 크기입니다.

포인터를 읽을 것이기 때문에 여기에는 4를 지정하면 됩니다.

네번째와 다섯번째 인자는 여기서 중요하지 않기 때문에 그냥 비워두었습니다.

그리고 여섯번째 인자로 성공의 여부가 들어오게 됩니다.

이렇게 해서 가상메모리를 읽거나 쓸 수가 있습니다.

그럼 3부에서 계속하겠습니다.

 

 

이제 진짜 끝인가 하시겠지만 사실 조금 더 있습니다.

가상메모리는 그냥 읽고 쓸 수 없습니다. 이걸 읽고 쓰려면 그에 맞는 권한(Privilege)

를 획득해야 하는데, 이 권한을 조절할 줄 알면 많은 것을 할 수 있습니다(^^훗)

이 권한을 통해 할 수 있는 일에 비해 이를 얻는 방법은 매우 쉽습니다.

Native API따위를 이용하지 않아도 됩니다.

이부분은 인터넷에 자료가 많이 있으므로 소스만 올리겠습니다.

TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} };
LookupPrivilegeValue(0, lpName, &priv.Privileges[0].Luid);
HANDLE hToken;
OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof(TOKEN_PRIVILEGES), 0, 0);
CloseHandle(hToken);

권한에는 여러 종류가 있는데, 그 중에는 셧다운 권한, 디버그 권한 등이 있습니다.

이름에서 예측할 수 있지만, 셧다운 권한은 컴퓨터를 시스템 종료할 수 있는 권한입니다.

이를 획득한 후 ExitWindows와 같은 함수를 이용하면 간단히 시스템 종료를 할 수 있습니다.

중요한 것은 디버그 권한입니다.

이 권한은 매우 강력한 권한으로, 이 권한을 획득해야만 가상메모리를 읽거나 쓸 수 있습니다.

(여담이지만)추가로, 이 권한을 얻으면 작업관리자도 종료하지 못하는 중대한

프로세스들을 죽일 수 있습니다.

이러한 프로세스들이 그냥은 Terminate되지 않는 이유는 OpenProcess함수가 NULL을

리턴하기 때문인데요, 그 이유는 PROCESS_ALL_ACCESS권한으로 프로세스를 열려면

디버그 권한이 필요하기 때문입니다.

따라서 디버그 권한을 얻은 뒤 OpenProcess를 하면 정상적으로 핸들을 얻게 되고,

TerminateProcess도 정상적으로 동작합니다.

이 방법을 이용하면 smss.exe, winlogon.exe등을 죽일 수가 있는데,

실험해 본 결과 이럴 경우 블루스크린이 뜨면서 바로 재부팅됩니다;;



어떠셨는지요;;;; 아마 프로세스 숨기는 법에 대해 궁금해 하셨던 분이 많을 겁니다.

저도 그렇습니다.

드라이버 개발자도 아니면서 이걸 궁금해 하는 이유는 하나 뿐이죠..

악성프로그램 제작.

그 증거로 이건 제가 중국 해커싸이트 여기저기 돌아다니면서 종합한 겁니다.

저라고 남말할 처지는 아니지만 .. 악용하지 말아주셨으면 합니다;;

그런 의미에서 전체 소스는 제시하지 않습니다.

(아니..사실 권한을 얻는 소스만 해도 충분히 악용될 수 있겠군요..;;)

죄송합니다; 앞으로는 소스가 제공될 수 없게 &#46124;습니다;; 사정이 생겨서;;

#pragma 의 쓰임새

아직 #pragma까진 써본적 없지만, 앞으로 필요할것 같아서 퍼왔음

#pragma는 define 이나 include와 같이 #으로 시작하는 전처리구문(precompiler)의 하나이다.
컴파일러에 종속적인 구문이라 컴파일러가 변경되었을 경우 제대로된 동작을 보장하지 못하므로 프로젝트 진행중에 서로 다른 컴파일러를 사용한다면 사용하지 않음이 바람직 하겠다.
- 대신 대체하는 문법을 사용해야 되겠다.

#pragma once
이것은 "컴파일러에게 한번만 컴파일해!" 라고 명령한다.
헤더의 중복을 막아준다.
무슨말인가 하면

a.h를 구현한 a.cpp, a.h는 독립적이다.(include가 없다.)
b.h를 구현한 b.cpp, c.h, a.h순서로 include
c.h를 구현한 c.cpp, a.h를 include

컴파일하면 b.h에서 c.h를 포함시키라고 되어있네? 하고 c.h에 들어가고 어? a.h를 포함하라고 그러네? 이러고 a.h를 포함한 c.h가 b.h로 돌아온다 그리고 a.h를 포함하라는 명령을 받고 a.h를 추가하다보면 같은 변수와 함수선언이 되어있다. 에러에러~
같은 선언이 두 번 반복되니 당연히 충돌이 난다. 컴파일러가 똑똑하여 단순히 경고 처리만 해주고 알아서 하나로 종합해줄 수도 있지만 대부분의 기본적인 컴파일러는 이건 아니잖아~ 한다.

이럴 때 써주는 것이다. pragma once
이는 c기본문법을 사용하여 구현할 수 있다.

#ifdef _MYCOMPILECK
#define _MYCOMPILECK
// 헤더 파일의 내용 선언
#endif



#pragma comment()
기본적인 pragma comment()의 형식은 다음과 같다.

#pragma comment( comment-type, ["comment string"] )

[] 안의 구문은 comment-type에 따라 필요할 경우 사용하는 것이다.
comment type에는 compiler, exestr, lib, linker, user 등이 올 수 있다.

#pragma comment( linker, "/subsystem:windows" )
#pragma comment( linker, "/subsystem:console" )

linker 를 사용하면 프로젝트를 console application인지 win32 application인지 명시해줄 수 있다.

또한 섹션의 설정을 할 수 있다.

#pragme comment( linker, "SECTION:.SHAREDATA,RWS" )

#pragma data_seg("SHAREDATA") 와 함께 사용하여 공유 메모리를 생성한다.
위의 명령어 대신 def 파일 안에 아래와 같이 해주어도 된다.

SECTIONS
SHAREDATA READ WRITE SHARED


이 중 가장 대표적인 사용법은 명시적인 라이브러리의 링크이다.

#pragma comment(lib, "xxxx.lib")

와 같이 사용하여 해당 라이브러리를 링크시켜 준다.
여러사람이 같이 수행하는 프로젝트의 경우 이와 같은 방법을 사용하여 lib를 링크하는 것이 라이브러리가 링크되어있다는 사실을 알기에도 좋고 굳이 주석다라 설명할 필요도 없어 좋지 않나 싶다. (있다는 사실은 알지만 아직 프로젝트 수행중 실제로 사용해 본적은 없음)



#pragma data_seg()
pragma data_seg()의 형식은 다음과 같다.

#pragma data_seg( ["section-name"[, "section-class"] ] )

[]는 사용하지 않아도 된다는 의미이다.

#pragma data_seg( "SHAREDATA" )
int x;
char y;
#pragma data_seg()

DLL 파일을 만들어보면서 제일 많이 사용해 보았고 가장 헷갈려 했던 부분이기도 하다.
DLL의 데이터 공유를 하기 위해 사용한다.
공유할 섹션을 만드는 것이다. 위의 명령어는 필수적으로 위에서 사용된 두 가지중 한가지 방법과 함께 사용 되어야 한다.

#pragme comment( linker, "SECTION:.SHAREDATA,RWS" )
SECTIONS
SHAREDATA READ WRITE SHARED

둘 다 해당 SECTION(SHAREDATA)의 허용 범위(?속성?)를 설정하는 것이다. READ, WRITE, SHARED 세 가지를 쓴다는 의미~
해당 사항에 대해 msdn에서 자세한 정보를 발견하지 못해 적지 못하였다(검색능력의 부족!!)
이제 변수 x와 y는 해당 dll을 사용하는 외부 파일과 같이 공유할 수 있는 변수가 되었다.(외부에서 접근 가능하게 되었다.)

이렇게 공유하는 변수는 물론 new로 메모리를 할당한 변수도 공유 가능하다.
특히 new 나 memalloc(이건 아직 미확인이지만 같은 메모리 할당이므로 가능할 것으로 본다)으로 메모리할당한 변수들은 dll외부에서도 해제(delete) 가능하다.



#pragma warning
특정 경고를 끄고 싶을 때 사용한다.
비 쥬얼 스튜디오의 버전이 다르기 때문에 뜨는 경고는 더더욱이 귀찮은 존재이다.(하지만 수정해서 손해볼 것은 없다. 그것이 곧 버그로 이어질 수 있기 때문이다. 특히 형변환의 경우 강제 캐스팅하여 확실히 명시해주는 것이 좋다. 일부러 그 값을 떼어낸다는 프로그래머의 의지를 컴파일러에게 보여주자. 부지런할수록 후에 손이 가는 일이 적어진다. 노력하자~)

형식은 이와 같다.

#pragma warning( warning-specifier : warning-number-list [; warning-specifier : warning-number-list...] )
#pragma warning( push[ ,n ] )
#pragma warning( pop )

실제 사용은 아래와 같이 한다.

#pragma warning( disable:4996 )




#pragma message()
컴파일 중에 메세지를 뿌려준다.
말이 필요없다-.-/

#pragma message("merong")