2014-11-12 3 views
3

실험 목적을 위해 DLL에서 내보낼 수없는 함수에 액세스하려고합니다. 왜 이것이 나쁜 생각인지 명백한 이유를 논의하지 않고 ...액세스 위반이 아닌 내 보낸 된 DLL 함수를 호출하는 C++

나는 정확한 함수 프로토 타입을 만들었고, 코드가 내가 원하는 모듈에서 오프셋으로 점프하고 있는지 확인할 수 있습니다.

는 C++ 코드

typedef int (__stdcall *FN)(int,wchar_t *); 

const DWORD_PTR funcOffset = 0x6F5B9; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    FN myFunction; 
    DWORD dwResult; 
    HMODULE hModule=LoadLibrary(L"undocumented.dll"); 

if (hModule != NULL) 
{ 
    DWORD_PTR funcAddress = (DWORD_PTR)GetProcAddress(hModule, "DllRegisterServer") + funcOffset; 
    myFunction = (FN)funcAddress; 
    wchar_t input[] = L"someinputdata"; 
    int result = myFunction(0,input); 
    std::cout << "Result: " << result << std::endl; 
} 
else 
{ 
    dwResult = GetLastError(); 
    std::cerr << "Failed: " << dwResult << std::endl; 
} 
return 0; 

}

함수 오프셋 점프하지만, I는 MOV [ESI + 8], EAX에서 액세스 위반을 얻는다. 나는이

mov  edi, edi 
push ebp 
mov  ebp, esp 
sub  esp, 0Ch 
cmp  [ebp+<wchar_t *>], 0 
push esi 
mov  esi, ecx 
jz  short <some location> ; doesn't jump 
push [ebp+<wchar_t *>]  
call ds:_wcsdup 
mov  [esi+8], eax <- access violation 

ECX가 호출 DS에 설정된 방지하기 위해 무엇을 할 수 : _wcsup :

__wcsdup: 
75DBEFA3 mov   edi,edi 
75DBEFA5 push  ebp 
75DBEFA6 mov   ebp,esp 
75DBEFA8 cmp   dword ptr [ebp+8],0 
75DBEFAC je   __wcsdup+2161Ah (75DE05BDh) 
75DBEFB2 mov   ecx,dword ptr [ebp+8] 
75DBEFB5 push  edi 
75DBEFB6 xor   edi,edi 
75DBEFB8 lea   edx,[ecx+2] 
75DBEFBB mov   ax,word ptr [ecx] 
75DBEFBE add   ecx,2 
75DBEFC1 cmp   ax,di 
75DBEFC4 jne   __wcsdup+18h (75DBEFBBh) 
75DBEFC6 sub   ecx,edx 
75DBEFC8 sar   ecx,1 
75DBEFCA push  ebx 
75DBEFCB push  2 
75DBEFCD lea   ebx,[ecx+1] 
75DBEFD0 push  ebx 
75DBEFD1 call  _calloc (75DBBE55h) 
75DBEFD6 mov   edi,eax 
75DBEFD8 pop   ecx 
75DBEFD9 pop   ecx 
75DBEFDA test  edi,edi 
75DBEFDC je   __wcsdup+2161Eh (75DE05C1h) 
75DBEFE2 push  dword ptr [ebp+8] 
75DBEFE5 push  ebx 
75DBEFE6 push  edi 
75DBEFE7 call  _wcscpy_s (75DBBB70h) 
75DBEFEC add   esp,0Ch 
75DBEFEF test  eax,eax 
75DBEFF1 jne   __wcsdup+5626Fh (75E15212h) 
75DBEFF7 mov   eax,edi 
75DBEFF9 pop   ebx 
75DBEFFA pop   edi 
75DBEFFB pop   ebp 
75DBEFFC ret 
+1

저는 x86 어셈블러를 잘 모릅니다. 'ecx'는 어디에 설정되어 있습니까? (이 값은 AV가 발생하는 주소 인 'esi'에 들어갑니다.) 당신은 프리 앰블 대신 함수의 중간으로 뛰어들 가능성이 있습니까? 호출 규칙이'__stdcall'이 아닌 것이 가능한가? – Cameron

+1

오프셋이 맞습니까? 'fn'에'0x6F5B9'을 추가하는 것은'fn'을'0x6F5B9' 바이트만큼 진행하지 않고'0x6F5B9 * sizeof (DWORD)'바이트만큼 진행합니다. –

+0

ecx가 ds : _wcsdup –

답변

2

이 코드는 ECX에서 의미있는 값을 예상하는 어셈블리에서 분명하다.

mov  edi, edi 
push ebp 
mov  ebp, esp 
sub  esp, 0Ch 
cmp  [ebp+<wchar_t *>], 0 
push esi 
mov  esi, ecx !! ecx has not been written to before here, now it is read 

이 기능은 stdcall입니다. stdcall 함수의 경우 ECX 값은 입력시 잘못 정의됩니다. 그래서 그 함수가 stdcall이 아니라는 것이 꽤 분명하다고 말하고 싶습니다. 사용되는 입력 인수의 유일한 명백한 표시는 ECX의 사용입니다. 그래서 ECXthis 포인터를 전달하는 thiscall 멤버 함수라고 말하고 싶습니다.

위의 모든 내용에 대해 100 % 확신 할 수는 없습니다. 리버스 엔지니어링은 최고의 시간에 충분히 어렵지 만 우리가 제공 한 정보만으로 작업한다는 것을 명심하십시오.

+0

문제는 확실히 __stdcall은 잘못된 선택입니다. 나는 교정 옵션을 운동 할 것이다.__fastcall (및 추가 입력 매개 변수)을 사용하는 새로운 프로토 타입은 액세스 위반을 제거합니다. 이제 경고 됨 ESP 값이 함수 호출을 통해 올바르게 저장되지 않았으므로 정확한 호출 패턴에 대해 더 많은 조사가 필요함을 나타냅니다. –

+0

추가 연구에 따르면 호출하는 컨벤션이 가장 가능성이 높습니다. 이 프로토 타입을 사용하면 충돌 및 ESP 오류가 제거되었습니다. typedef int (__thiscall * FN) (wchar_t *, wchar_t *, wchar_t *); - 사용 된 "계급"구조를 확인하기 위해서는 더 많은 연구가 필요하지만. ECX를 확인하는 팁으로 __thiscall이 ECX를 사용하는 다른 호출 규칙이라는 것을 알았습니다. http://msdn.microsoft.com/en-us/library/984x0h58.aspx –

+0

현재로서는 함수가 부분적으로 첫 번째 매개 변수 인 struct struct1 { \t char something [8]; \t wchar_t * iValue;} <- esi + 8을 찾고자하는 출력은 여기에 설정된 문자열에 대한 포인터입니다 –

관련 문제