首页
社区
课程
招聘
[求助]CreateRemoteThread Debug异常而Release正常
发表于: 2013-6-24 00:09 6415

[求助]CreateRemoteThread Debug异常而Release正常

2013-6-24 00:09
6415
这段代码在VS2008 Win7下编译
Release 下通过
Debug下到WaitForSingleObject 有异常
0xC0000005: Access violation

本人新手+菜鸟
苦苦baidu&google半夜未果
求高手解答
Thanks in advance.
PS:
代码非本人写的
来自这里
http://win32.mvps.org/processes/remthread.html

// demonstrates getting the command line of another process
// requires PROCESS_CREATE_THREAD, PROCESS_VM_OPERATION,
// PROCESS_VM_WRITE, PROCESS_VM_READ to the target, or the
// SeDebugPrivilege

// *** You *must* remove "/GZ" from the debug build settings ***
// (If you use my (felixk's) project file, this has already happened)

#include "stdafx.h"


#define lenof(x) ( sizeof (x) / sizeof ((x)[0]) )

typedef const wchar_t *(__stdcall *tGCLW)( void );

const DWORD MAXINJECTSIZE = 4096;

struct Common
{
  DWORD gle; // last error from remote thread
  tGCLW pGCLW; // address of GetCommandLineW()
  wchar_t str[2000]; // the command line buffer
};


// try to enable SeDebugPrivilege
void EnableDebugPriv( void );
// inject function bem() into target process
bool Bugger( HANDLE h, wstring &str );
// and this is the code we are injecting
DWORD __stdcall bem( Common *c );


int wmain( int argc, wchar_t *argv[] )
{
  int i;
  DWORD pid;
  HANDLE h;
  wstring str;

  if ( argc == 1 )
  {
    wcout << endl << L"usage: remthread pid [pid ...]" << endl;
    wcout << L"Reports the command lines of the specified processes." << endl;
    wcout << L"Use \"-1\" to have the program look at itself." << endl;
    return 1;
  }

  EnableDebugPriv();
  for ( i = 1; i < argc; ++ i )
  {
    wstringstream( argv[i] ) >> pid;
    if ( pid == (DWORD) -1 )
      pid = GetCurrentProcessId();
    wcout << L"pid " << pid << L": ";
    h = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
      PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid );
    if ( h != 0 )
    {
      if ( Bugger( h, str ) )
        wcout << endl << L"    \"" << str.c_str() << L"\"";
      CloseHandle( h );
      wcout << endl;
    }
    else
      wcout << L"open failed, gle = " << GetLastError() << endl;
  }

  return 0;
}



void EnableDebugPriv( void )
{
  HANDLE hToken;
  LUID sedebugnameValue;
  TOKEN_PRIVILEGES tkp;

  if ( ! OpenProcessToken( GetCurrentProcess(),
    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
  {
    wcout << L"OPT() failed, gle = " << GetLastError() <<
      L" SeDebugPrivilege is not available." << endl;
    return;
  }

  if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
  {
    wcout << L"LPV() failed, gle = " << GetLastError() <<
      L" SeDebugPrivilege is not available." << endl;
    CloseHandle( hToken );
    return;
  }

  tkp.PrivilegeCount = 1;
  tkp.Privileges[0].Luid = sedebugnameValue;
  tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

  if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
    wcout << L"ATP() failed, gle = " << GetLastError() <<
      L" SeDebugPrivilege is not available." << endl;

  CloseHandle( hToken );
}



bool Bugger( HANDLE h, wstring &str )
{
  HANDLE ht = 0;
  void *p = 0;
  Common *c = 0;
  bool result = false;
  DWORD rc;
  HMODULE hk32 = 0;
  Common localCopy;

  // allocate memory
  p = VirtualAllocEx( h, 0, MAXINJECTSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
  if ( p == 0 )
  {
    wcout << L"VAE() failed, gle = " << GetLastError();
    goto cleanup;
  }

  c = (Common *) VirtualAllocEx( h, 0, sizeof Common, MEM_COMMIT, PAGE_READWRITE );
  if ( c == 0 )
  {
    wcout << L"VAE() failed, gle = " << GetLastError();
    goto cleanup;
  }

  // copy function there
  if ( ! WriteProcessMemory( h, p, &bem, MAXINJECTSIZE, 0 ) )
  {
    wcout << L"WPM() failed, gle = " << GetLastError();
    goto cleanup;
  }

  // initialize data area for remote guy
  hk32 = LoadLibrary( L"kernel32.dll" );
  if ( hk32 == 0 )
  {
    wcout << L"LL() failed, gle = " << GetLastError();
    goto cleanup;
  }
  localCopy.gle = 0;
  localCopy.pGCLW = (tGCLW) GetProcAddress( hk32, "GetCommandLineW" );
  if ( localCopy.pGCLW == 0 )
  {
    wcout << L"GPA() failed, gle = " << GetLastError();
    goto cleanup;
  }
  FreeLibrary( hk32 );
  hk32 = 0;
  localCopy.str[0] = L'\0';
  if ( ! WriteProcessMemory( h, c, &localCopy, sizeof localCopy, 0 ) )
  {
    wcout << L"WPM() failed, gle = " << GetLastError();
    goto cleanup;
  }

  // CreateRemoteThread()
  ht = CreateRemoteThread( h, 0, 0, (DWORD (__stdcall *)( void *)) p, c, 0, &rc );
  if ( ht == NULL )
  {
    wcout << L"CRT() failed, gle = " << GetLastError();
    goto cleanup;
  }

  rc = WaitForSingleObject( ht, 3000 );
  switch ( rc )
  {
  case WAIT_TIMEOUT:
    wcout << L"WFSO() timed out. Odd!";
    goto cleanup;
  case WAIT_FAILED:
    wcout << L"WFSO() failed, gle = " << GetLastError();
    goto cleanup;
  case WAIT_OBJECT_0:
    // this might just have worked, pick up the result!
    if ( ! ReadProcessMemory( h, c, &localCopy, sizeof localCopy, 0 ) )
    {
      wcout << L"RPM() failed, gle = " << GetLastError();
      goto cleanup;
    }
    if ( localCopy.gle == 0 )
    {
      str = localCopy.str;
      result = true;
      wcout << L"successfully buggered.";
    }
    else
      wcout << L"Remote thread failed, gle = " << localCopy.gle;
    break;
  default:
    wcout << L"WFSO() returned a surprise! rc = " <<
      rc << L", gle = " << GetLastError();
    break;
  }

cleanup:
  CloseHandle( ht );
  if ( p != 0 )
    VirtualFreeEx( h, p, 0, MEM_RELEASE );
  if ( c != 0 )
    VirtualFreeEx( h, c, 0, MEM_RELEASE );
  if ( hk32 != 0 )
    FreeLibrary( hk32 );

  return result;
}


// The whole shebang makes a number of assumptions:
// -- target process is a Win32 process
// -- kernel32.dll loaded at same address in each process (safe)
// -- bem() shorter than MAXINJECTSIZE
// -- bem() does not rely on the C/C++ runtime
// -- /GZ is _not_ used. (If it is, the compiler generates calls
//    to functions which are not injected into the target. Oops!
DWORD __stdcall bem( Common *c )
{
  const wchar_t *src;
  wchar_t *tgt, *end;

  // __asm int 3;
  src = c->pGCLW();
  tgt = &c->str[0];
  end = &c->str[lenof( c->str ) - 1];
  if ( src == 0 || tgt == 0 || end == 0 )
  {
    c->gle = 998;
    return 0;
  }

  for ( ;  *src != L'\0' && tgt < end; ++ src, ++ tgt )
    *tgt = *src;
  *tgt = L'\0';
  c->gle = 0;

  return 0;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 248
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
MARK下,我也遇到了这问题,未解决
2013-6-24 00:25
0
雪    币: 53
活跃值: (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
debug的link increment 去掉试试。
2013-6-24 00:28
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
去掉了可以通过了
请问原因是什么
谢谢!
2013-6-24 20:28
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
5
我也得瑟一下。
一定不是WaitForSingleObject抛得异常。
其实是
 // copy function there
  if ( ! WriteProcessMemory( h, p, &bem, MAXINJECTSIZE, 0 ) )

导致的问题,在远程线程执行的时候该线程抛0xC0000005.

这个问题是Debug版本编译的时候使用增量编译,导致每个函数都是用一个Thunk

你在Copy函数代码的时候,其实只Copy了Thunk,导致Copy的Thunk找不到函数真正的实体,从而崩溃。

用OD附加一下就知道答案了,遇到这种问题还是要自己动手调试解决
2013-6-25 09:47
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
Thanks a lot, man.
2013-6-25 23:01
0
游客
登录 | 注册 方可回帖
返回
//