擦除模块痕迹
来源:互联网 发布:javascript框架是什么 编辑:程序博客网 时间:2024/04/28 15:48
对于擦除模块痕迹,我实验了两种方法,下面一一阐述:
1.修改PEB结构,用代码说话
typedef struct _PEB_LDR_DATA
...{
ULONG Length;
BOOLEAN Initialized;
BYTE reserved[3];
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _UNICODE_STRING
...{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _LDR_MODULE ...{
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;
typedef struct RTL_DRIVE_LETTER_CURDIR
...{
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
UNICODE_STRING DosPath;
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
typedef struct _RTL_USER_PROCESS_PARAMETERS
...{
ULONG AllocationSize;
ULONG Size;
ULONG Flags;
ULONG DebugFlags;
HANDLE hConsole;
ULONG ProcessGroup;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
UNICODE_STRING CurrentDirectoryName;
HANDLE CurrentDirectoryHandle;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PWSTR Environment;
ULONG dwX;
ULONG dwY;
ULONG dwXSize;
ULONG dwYSize;
ULONG dwXCountChars;
ULONG dwYCountChars;
ULONG dwFillAttribute;
ULONG dwFlags;
ULONG wShowWindow;
UNICODE_STRING WindowTitle;
UNICODE_STRING Desktop;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeInfo;
RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef VOID (_stdcall *PPEBLOCKROUTINE)(PVOID);
typedef struct _PEB_FREE_BLOCK
...{
struct _PEB_FREE_BLOCK* Next;
ULONG Size;
} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;
struct _NT_PEB
...{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA LoaderData;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PPEBLOCKROUTINE FastPebLockRoutine;
PPEBLOCKROUTINE FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount;
PVOID *KernelCallbackTable;
PVOID EventLogSection;
PVOID EventLog;
PPEB_FREE_BLOCK FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PVOID *ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
BYTE Spare2[0x4];
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID **ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributeList;
PVOID LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
ULONG OSBuildNumber;
ULONG OSPlatformId;
ULONG ImageSubSystem;
ULONG ImageSubSystemMajorVersion;
ULONG ImageSubSystemMinorVersion;
ULONG GdiHandleBuffer[0x22];
ULONG PostProcessInitRoutine;
ULONG TlsExpansionBitmap;
BYTE TlsExpansionBitmapBits[0x80];
ULONG SessionId;
};
typedef struct _CLIENT_ID
...{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef struct _GDI_TEB_BATCH
...{
ULONG Offset;
ULONG HDC;
ULONG Buffer[0x136];
} GDI_TEB_BATCH, *PGDI_TEB_BATCH;
struct _NT_TEB
...{
NT_TIB Tib; /**//* 00h */
PVOID EnvironmentPointer; /**//* 1Ch */
CLIENT_ID Cid; /**//* 20h */
PVOID ActiveRpcInfo; /**//* 28h */
PVOID ThreadLocalStoragePointer; /**//* 2Ch */
_NT_PEB *Peb; /**//* 30h */
ULONG LastErrorValue; /**//* 34h */
ULONG CountOfOwnedCriticalSections; /**//* 38h */
PVOID CsrClientThread; /**//* 3Ch */
void* Win32ThreadInfo; /**//* 40h */
ULONG Win32ClientInfo[0x1F]; /**//* 44h */
PVOID WOW32Reserved; /**//* C0h */
LCID CurrentLocale; /**//* C4h */
ULONG FpSoftwareStatusRegister; /**//* C8h */
PVOID SystemReserved1[0x36]; /**//* CCh */
PVOID Spare1; /**//* 1A4h */
LONG ExceptionCode; /**//* 1A8h */
UCHAR SpareBytes1[0x28]; /**//* 1ACh */
PVOID SystemReserved2[0xA]; /**//* 1D4h */
GDI_TEB_BATCH GdiTebBatch; /**//* 1FCh */
ULONG gdiRgn; /**//* 6DCh */
ULONG gdiPen; /**//* 6E0h */
ULONG gdiBrush; /**//* 6E4h */
CLIENT_ID RealClientId; /**//* 6E8h */
PVOID GdiCachedProcessHandle; /**//* 6F0h */
ULONG GdiClientPID; /**//* 6F4h */
ULONG GdiClientTID; /**//* 6F8h */
PVOID GdiThreadLocaleInfo; /**//* 6FCh */
PVOID UserReserved[5]; /**//* 700h */
PVOID glDispatchTable[0x118]; /**//* 714h */
ULONG glReserved1[0x1A]; /**//* B74h */
PVOID glReserved2; /**//* BDCh */
PVOID glSectionInfo; /**//* BE0h */
PVOID glSection; /**//* BE4h */
PVOID glTable; /**//* BE8h */
PVOID glCurrentRC; /**//* BECh */
PVOID glContext; /**//* BF0h */
LONG LastStatusValue; /**//* BF4h */
UNICODE_STRING StaticUnicodeString; /**//* BF8h */
WCHAR StaticUnicodeBuffer[0x105]; /**//* C00h */
PVOID DeallocationStack; /**//* E0Ch */
PVOID TlsSlots[0x40]; /**//* E10h */
LIST_ENTRY TlsLinks; /**//* F10h */
PVOID Vdm; /**//* F18h */
PVOID ReservedForNtRpc; /**//* F1Ch */
PVOID DbgSsReserved[0x2]; /**//* F20h */
ULONG HardErrorDisabled; /**//* F28h */
PVOID Instrumentation[0x10]; /**//* F2Ch */
PVOID WinSockData; /**//* F6Ch */
ULONG GdiBatchCount; /**//* F70h */
USHORT Spare2; /**//* F74h */
BOOLEAN IsFiber; /**//* F76h */
UCHAR Spare3; /**//* F77h */
ULONG Spare4; /**//* F78h */
ULONG Spare5; /**//* F7Ch */
PVOID ReservedForOle; /**//* F80h */
ULONG WaitingOnLoaderLock; /**//* F84h */
ULONG Unknown[11]; /**//* F88h */
PVOID FlsSlots; /**//* FB4h */
PVOID WineDebugInfo; /**//* Needed for WINE DLL's */
};
static struct _NT_TEB* GetCurrentThreadTEB() //获得TEB
...{
struct _NT_TEB *pTeb=NULL;
_asm
...{
mov eax,fs:[0x18]
mov pTeb,eax
}
return pTeb;
}
void HideModule(std::string strModuleName)
...{
struct _NT_TEB *pTeb = GetCurrentThreadTEB();
struct _NT_PEB *pPeb = pTeb->Peb; //由TEB获得PEB
PPEB_LDR_DATA pLdrData = pPeb->LoaderData;
PLDR_MODULE pFirstLdrModule = (PLDR_MODULE)pLdrData->InLoadOrderModuleList.Flink;
PLDR_MODULE pLdrModule = pFirstLdrModule;
PLDR_MODULE pLastModule,pNextModule;
//名字通通转为WideChar,因此Windows内部是Unicode的
WCHAR pWStrModuleName[MAX_PATH] = ...{WCHAR(0)};
MultiByteToWideChar(CP_ACP,0,strModuleName.c_str(), -1,pWStrModuleName,strModuleName.size());
//PEB里面有当前进程的模块列表,ToolHelp里面的函数就是根据这个列表来遍历的因此,修改此列表可以达到隐藏的目的
do
...{
//判断是否是我们要屏蔽的模块
if(wcscmp(pLdrModule->BaseDllName.Buffer, pWStrModuleName) == 0)
...{
//更改指针,达到隐藏的目的
pLastModule = (PLDR_MODULE)(pLdrModule->InLoadOrderModuleList.Blink);
pNextModule = (PLDR_MODULE)(pLdrModule->InLoadOrderModuleList.Flink);
pLastModule->InLoadOrderModuleList.Flink = (PLIST_ENTRY)pNextModule;
pNextModule->InLoadOrderModuleList.Blink = (PLIST_ENTRY)pLastModule;
//因为PEB里面有三个列表(分别是以Load顺序、地址顺序、初始化顺序来排序),所以通过覆盖的方式修改另外两个列表,达到隐藏的目的
pLdrModule->BaseAddress = pLastModule->BaseAddress;
pLdrModule->BaseDllName = pLastModule->BaseDllName;
pLdrModule->EntryPoint = pLastModule->EntryPoint;
pLdrModule->Flags = pLastModule->Flags;
pLdrModule->FullDllName = pLastModule->FullDllName;
pLdrModule->HashTableEntry = pLastModule->HashTableEntry;
pLdrModule->LoadCount = pLastModule->LoadCount;
pLdrModule->SizeOfImage = pLastModule->SizeOfImage;
pLdrModule->TimeDateStamp = pLastModule->TimeDateStamp;
pLdrModule->TlsIndex = pLastModule->TlsIndex;
}
pLdrModule = (PLDR_MODULE)pLdrModule->InLoadOrderModuleList.Flink;
} while(pLdrModule != pFirstLdrModule);
}
...{
ULONG Length;
BOOLEAN Initialized;
BYTE reserved[3];
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _UNICODE_STRING
...{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _LDR_MODULE ...{
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;
typedef struct RTL_DRIVE_LETTER_CURDIR
...{
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
UNICODE_STRING DosPath;
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
typedef struct _RTL_USER_PROCESS_PARAMETERS
...{
ULONG AllocationSize;
ULONG Size;
ULONG Flags;
ULONG DebugFlags;
HANDLE hConsole;
ULONG ProcessGroup;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
UNICODE_STRING CurrentDirectoryName;
HANDLE CurrentDirectoryHandle;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PWSTR Environment;
ULONG dwX;
ULONG dwY;
ULONG dwXSize;
ULONG dwYSize;
ULONG dwXCountChars;
ULONG dwYCountChars;
ULONG dwFillAttribute;
ULONG dwFlags;
ULONG wShowWindow;
UNICODE_STRING WindowTitle;
UNICODE_STRING Desktop;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeInfo;
RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef VOID (_stdcall *PPEBLOCKROUTINE)(PVOID);
typedef struct _PEB_FREE_BLOCK
...{
struct _PEB_FREE_BLOCK* Next;
ULONG Size;
} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;
struct _NT_PEB
...{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA LoaderData;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PPEBLOCKROUTINE FastPebLockRoutine;
PPEBLOCKROUTINE FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount;
PVOID *KernelCallbackTable;
PVOID EventLogSection;
PVOID EventLog;
PPEB_FREE_BLOCK FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PVOID *ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
BYTE Spare2[0x4];
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID **ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributeList;
PVOID LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
ULONG OSBuildNumber;
ULONG OSPlatformId;
ULONG ImageSubSystem;
ULONG ImageSubSystemMajorVersion;
ULONG ImageSubSystemMinorVersion;
ULONG GdiHandleBuffer[0x22];
ULONG PostProcessInitRoutine;
ULONG TlsExpansionBitmap;
BYTE TlsExpansionBitmapBits[0x80];
ULONG SessionId;
};
typedef struct _CLIENT_ID
...{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef struct _GDI_TEB_BATCH
...{
ULONG Offset;
ULONG HDC;
ULONG Buffer[0x136];
} GDI_TEB_BATCH, *PGDI_TEB_BATCH;
struct _NT_TEB
...{
NT_TIB Tib; /**//* 00h */
PVOID EnvironmentPointer; /**//* 1Ch */
CLIENT_ID Cid; /**//* 20h */
PVOID ActiveRpcInfo; /**//* 28h */
PVOID ThreadLocalStoragePointer; /**//* 2Ch */
_NT_PEB *Peb; /**//* 30h */
ULONG LastErrorValue; /**//* 34h */
ULONG CountOfOwnedCriticalSections; /**//* 38h */
PVOID CsrClientThread; /**//* 3Ch */
void* Win32ThreadInfo; /**//* 40h */
ULONG Win32ClientInfo[0x1F]; /**//* 44h */
PVOID WOW32Reserved; /**//* C0h */
LCID CurrentLocale; /**//* C4h */
ULONG FpSoftwareStatusRegister; /**//* C8h */
PVOID SystemReserved1[0x36]; /**//* CCh */
PVOID Spare1; /**//* 1A4h */
LONG ExceptionCode; /**//* 1A8h */
UCHAR SpareBytes1[0x28]; /**//* 1ACh */
PVOID SystemReserved2[0xA]; /**//* 1D4h */
GDI_TEB_BATCH GdiTebBatch; /**//* 1FCh */
ULONG gdiRgn; /**//* 6DCh */
ULONG gdiPen; /**//* 6E0h */
ULONG gdiBrush; /**//* 6E4h */
CLIENT_ID RealClientId; /**//* 6E8h */
PVOID GdiCachedProcessHandle; /**//* 6F0h */
ULONG GdiClientPID; /**//* 6F4h */
ULONG GdiClientTID; /**//* 6F8h */
PVOID GdiThreadLocaleInfo; /**//* 6FCh */
PVOID UserReserved[5]; /**//* 700h */
PVOID glDispatchTable[0x118]; /**//* 714h */
ULONG glReserved1[0x1A]; /**//* B74h */
PVOID glReserved2; /**//* BDCh */
PVOID glSectionInfo; /**//* BE0h */
PVOID glSection; /**//* BE4h */
PVOID glTable; /**//* BE8h */
PVOID glCurrentRC; /**//* BECh */
PVOID glContext; /**//* BF0h */
LONG LastStatusValue; /**//* BF4h */
UNICODE_STRING StaticUnicodeString; /**//* BF8h */
WCHAR StaticUnicodeBuffer[0x105]; /**//* C00h */
PVOID DeallocationStack; /**//* E0Ch */
PVOID TlsSlots[0x40]; /**//* E10h */
LIST_ENTRY TlsLinks; /**//* F10h */
PVOID Vdm; /**//* F18h */
PVOID ReservedForNtRpc; /**//* F1Ch */
PVOID DbgSsReserved[0x2]; /**//* F20h */
ULONG HardErrorDisabled; /**//* F28h */
PVOID Instrumentation[0x10]; /**//* F2Ch */
PVOID WinSockData; /**//* F6Ch */
ULONG GdiBatchCount; /**//* F70h */
USHORT Spare2; /**//* F74h */
BOOLEAN IsFiber; /**//* F76h */
UCHAR Spare3; /**//* F77h */
ULONG Spare4; /**//* F78h */
ULONG Spare5; /**//* F7Ch */
PVOID ReservedForOle; /**//* F80h */
ULONG WaitingOnLoaderLock; /**//* F84h */
ULONG Unknown[11]; /**//* F88h */
PVOID FlsSlots; /**//* FB4h */
PVOID WineDebugInfo; /**//* Needed for WINE DLL's */
};
static struct _NT_TEB* GetCurrentThreadTEB() //获得TEB
...{
struct _NT_TEB *pTeb=NULL;
_asm
...{
mov eax,fs:[0x18]
mov pTeb,eax
}
return pTeb;
}
void HideModule(std::string strModuleName)
...{
struct _NT_TEB *pTeb = GetCurrentThreadTEB();
struct _NT_PEB *pPeb = pTeb->Peb; //由TEB获得PEB
PPEB_LDR_DATA pLdrData = pPeb->LoaderData;
PLDR_MODULE pFirstLdrModule = (PLDR_MODULE)pLdrData->InLoadOrderModuleList.Flink;
PLDR_MODULE pLdrModule = pFirstLdrModule;
PLDR_MODULE pLastModule,pNextModule;
//名字通通转为WideChar,因此Windows内部是Unicode的
WCHAR pWStrModuleName[MAX_PATH] = ...{WCHAR(0)};
MultiByteToWideChar(CP_ACP,0,strModuleName.c_str(), -1,pWStrModuleName,strModuleName.size());
//PEB里面有当前进程的模块列表,ToolHelp里面的函数就是根据这个列表来遍历的因此,修改此列表可以达到隐藏的目的
do
...{
//判断是否是我们要屏蔽的模块
if(wcscmp(pLdrModule->BaseDllName.Buffer, pWStrModuleName) == 0)
...{
//更改指针,达到隐藏的目的
pLastModule = (PLDR_MODULE)(pLdrModule->InLoadOrderModuleList.Blink);
pNextModule = (PLDR_MODULE)(pLdrModule->InLoadOrderModuleList.Flink);
pLastModule->InLoadOrderModuleList.Flink = (PLIST_ENTRY)pNextModule;
pNextModule->InLoadOrderModuleList.Blink = (PLIST_ENTRY)pLastModule;
//因为PEB里面有三个列表(分别是以Load顺序、地址顺序、初始化顺序来排序),所以通过覆盖的方式修改另外两个列表,达到隐藏的目的
pLdrModule->BaseAddress = pLastModule->BaseAddress;
pLdrModule->BaseDllName = pLastModule->BaseDllName;
pLdrModule->EntryPoint = pLastModule->EntryPoint;
pLdrModule->Flags = pLastModule->Flags;
pLdrModule->FullDllName = pLastModule->FullDllName;
pLdrModule->HashTableEntry = pLastModule->HashTableEntry;
pLdrModule->LoadCount = pLastModule->LoadCount;
pLdrModule->SizeOfImage = pLastModule->SizeOfImage;
pLdrModule->TimeDateStamp = pLastModule->TimeDateStamp;
pLdrModule->TlsIndex = pLastModule->TlsIndex;
}
pLdrModule = (PLDR_MODULE)pLdrModule->InLoadOrderModuleList.Flink;
} while(pLdrModule != pFirstLdrModule);
}
2.手动完成dll的加载:刚开始研究手动加载的时候觉得比较复杂,但是通过实践之后,其实还是很简单的,代码比较长这里就不详加叙述了,我就用下面几个步骤来分别叙述:
- 首先要分配一个空间给dll,可以根据PE结构里面的SizeOfImage来分配;
- 然后把dll加载到分配的空间里面去,需要注意的是不能单纯拷贝,对于每个Section而言,需要安排到Section列表里面指定的虚拟地址偏移里面去(即RAV + 分配到的空间开始地址<可以称为模块句柄>);
- 然后要做的就是完成IAT的填写(根据INT)以及重定位表的处理
- ok,打完收工(还有些比较复杂的处理我还不太明白,比如TLS,努力学习中)
因为手动加载dll没有经过系统的干涉,所以上面的PEB结构里面也就不会有相应的模块结构,也就达到了隐藏的目的。
- 擦除模块痕迹
- (原创工具)CnCrypt磁盘痕迹擦除工具,彻底杜绝数据恢复。
- 擦除
- 擦除
- 记录痕迹
- 留点痕迹。。。
- 岁月痕迹
- 类型擦除
- 数据擦除
- graphic擦除
- 擦除UIImageView
- 图片擦除
- 擦除效果
- 什么是痕迹保留(转帖)
- 保留修改痕迹
- 留个痕迹先
- 十字路口的痕迹
- 留下好的痕迹
- vmware下如何安装FC5
- 浏览器窗口中出现滚动条
- 告别世界杯的日子
- 外行PK solaris8
- DBGridEh使用
- 擦除模块痕迹
- 美国人日常生活中常用的五星级句子
- 学习c++的50条忠告(初学者必看)
- Eclipse常用快捷键
- Google打不开的解决方法和IP地址表
- 在DELPHI中实现打印的预览
- 杂乱心情
- DrawText/DrawText,字符串换行和长字符串(word wrapping and long strings)
- 触发器入门级知识