免费高清特黄a大片,九一h片在线免费看,a免费国产一级特黄aa大,国产精品国产主播在线观看,成人精品一区久久久久,一级特黄aa大片,俄罗斯无遮挡一级毛片

分享

C++怎樣實現(xiàn)Win32 ASM中的invoke調(diào)用 [文字模式]

 quasiceo 2014-01-11

C++怎樣實現(xiàn)Win32 ASM中的invoke調(diào)用

bydarkst
2012-11-20, 21:34:35
不知道有沒有人能幫忙實現(xiàn)下面這樣一個invoke函數(shù)或者有更好的方法

DWORD invoke(char* lib, char* func_name, ...)
{
//這邊大概是這么寫
Farproc func = GetProcAddress(LoadLibrary(lib), func_name);
//下面就是把后面的不定參數(shù)傳遞給上面這個函數(shù)
return func(...);
}

//我覺得可能是要先取出參數(shù)個數(shù)va_list va_start va_end
//然后從后往前依次__asm push parma,最后call func
//但是感覺還是比較復雜,而且不夠通用(不一定是stdcall)

//這樣做的目的是不用通過導入表實現(xiàn)動態(tài)調(diào)用函數(shù),關鍵是這要是一個通用函數(shù)

調(diào)用如下:
invoke("kernel32.dll", "Sleep", 1000);
int nRet = invoke("user32.dll", "MessageBoxA", NULL, "hello", "info", MB_OK);
invoke("msvcrt.dll", "printf", "1+2=%d\n", 3);
lononan
2012-11-20, 22:59:13
以下是我成功測試MessageBoxA的例子,其他函數(shù)未測試:
73733


#include "stdafx.h"
#include <windows.h>
#include <stdarg.h>
/*****************************************
lib:庫文件
FucName:函數(shù)名
...:參數(shù),(注意,參數(shù)按匯編方式入棧,參數(shù)順序倒著寫)

*****************************************/
int myInvoke( char* lib,char* FucName ,...)
{
va_list arg_ptr;
int nResult;
int funAdd=(int)GetProcAddress(LoadLibrary(lib),FucName);
va_start(arg_ptr, FucName);
int p;
while((p=va_arg( arg_ptr, int ))!=-1)//如果p==-1表示結(jié)束
{
_asm push p;
}
_asm
{
call [funAdd];
mov nResult,eax
}

va_end(arg_ptr);
return nResult;
}
int main(int argc, char* argv[])
{

myInvoke("user32.dll","MessageBoxA",MB_YESNO,"標題","消息",0,-1);
//最后一個參數(shù)-1是結(jié)束標志

return 0;
}
LOVEZ
2012-11-20, 23:07:54
:confused: 有這個必要么
bydarkst
2012-11-21, 11:40:20
以下是我成功測試MessageBoxA的例子,其他函數(shù)未測試:
73733


#include "stdafx.h"
#include <windows.h>
#include <stdarg.h>
/*****************************************
lib:庫文...

謝謝你的回復:cool:
HOWMP
2012-11-21, 13:27:55
:o:挺難的,沒法判斷被調(diào)用函數(shù)的調(diào)用類型。MessageBoxA是__stdcall,printf是__cdecl。前者不需要invoke平衡堆棧,但后者需要。

這如何解決?
lononan
2012-11-21, 14:52:12
:o:挺難的,沒法判斷被調(diào)用函數(shù)的調(diào)用類型。MessageBoxA是__stdcall,printf是__cdecl。前者不需要invoke平衡堆棧,但后者需要。

這如何解決?

經(jīng)測試,
myInvoke("msvcrt.dll","printf","sss\n",-1);
system("pause");
成調(diào)用啊,不過Debug版本會提示錯誤,而Release正常,通常我們都是用Release版本吧?
HOWMP
2012-11-21, 16:01:31
:3:LS歡迎討論。
我覺得你寫這個以-1結(jié)尾有點牽強,如果參數(shù)里有-1怎么辦?豈不是悲劇了。
至于release能成功的原因

PUSH EBP
MOV EBP,ESP
……
POP EBP
RETN

debug不成功是因為每次CALL調(diào)用都有退棧平衡檢查




// invoke.cpp : 定義控制臺應用程序的入口點。
//

#include "stdafx.h"
#include <windows.h>

/*
0012FF64 |0040103D 返回到 invoke.0040103D 來自 invoke.00401000
0012FF68 |00402110 ASCII "user32.dll"
0012FF6C |00402104 ASCII "MessageBoxA"
0012FF70 |00000000
0012FF74 |004020FC ASCII "hello"
0012FF78 |004020F4 ASCII "info"
0012FF7C |00000000

*/


#define MEMCPY(pDest,pSource,S) \
__asm mov edi,pDest \
__asm mov esi,pSource \
__asm mov ecx,S \
__asm xor eax,eax \
__asm cld \
__asm lodsb \
__asm stosb \
__asm dec ecx \
__asm test ecx,ecx \
__asm _emit 0x75 \
__asm _emit 0xF9


#define NAKED __declspec(naked)

int NAKED invoke(char* lib,char* funname ,...)
{
PULONG stack,arg;
ULONG argsize,bak_esp,fun;
__asm
{
mov stack,esp
}
//找到調(diào)用invoke的返回地址,add esp,0xx 即可計算參數(shù)個數(shù)
if(*(PUSHORT)stack[0] == 0xC483)
{
argsize = *(PUCHAR)(stack[0]+2) - 8;//invoke參數(shù)大小 減去8(2*4) 就是要調(diào)用函數(shù)的參數(shù)的大小
arg = &stack[3];
}
else
{
__asm mov eax,-1
goto RET;
}
fun = (ULONG)GetProcAddress(LoadLibraryA((PCHAR)stack[1]),(PCHAR)stack[2]);
__asm
{
mov bak_esp,esp
sub esp,argsize
MEMCPY(esp,arg,argsize)
call fun
mov esp,bak_esp //保證C調(diào)用的堆棧平衡
}


RET:
__asm
{
ret
}

}


int _tmain(int argc, _TCHAR* argv[])
{
invoke("kernel32.dll", "Sleep", 1000);
invoke("user32.dll", "MessageBoxA", NULL, "hello", "info", MB_OK);
invoke("msvcrt.dll", "printf", "1+2=%d\n", 3);


getchar();
return 0;
}



寫了這么一段,發(fā)現(xiàn)以下幾個問題:
0.網(wǎng)上查資料,不定參數(shù)函數(shù),要么和LZ一樣通過一個特定的參數(shù)如-1,來判斷參數(shù)個數(shù)。
要么就是參數(shù)個數(shù)也傳給函數(shù)。
1.不定參數(shù)函數(shù),由調(diào)用函數(shù)平衡堆棧,比如這里由main平衡invoke
2.由于1,所以invoke調(diào)用完成以后會有ADD ESP,XXX,根據(jù)這個原理可以通過這里判斷參數(shù)個數(shù)
3.當寫好之后,測試正常。但當三個invoke同時出現(xiàn)的時候,release悲劇了。編譯器直接優(yōu)化了,三次調(diào)用完成以后才進行堆棧平衡。所以前兩次均失敗。
4.printf通過什么方式判斷參數(shù)個數(shù)?

printf("%d\n%d\n%d\n",1);


1
4198786
1

猜測可能是根據(jù)%個數(shù)來確定參數(shù)個數(shù)。


于是,問題來了,到底有沒有一個通用的方法,來確定不定參數(shù)函數(shù)的參數(shù)個數(shù)?
lononan
2012-11-21, 16:43:54
那可以自定義結(jié)束標志的參數(shù)嘛。
NWmLWB
2012-11-21, 20:42:03
還沒寫過變參數(shù)的c函數(shù)呢,2樓方法不錯
HOWMP
2012-11-22, 14:09:38
那可以自定義結(jié)束標志的參數(shù)嘛。

:o:不管如何設置,總能出現(xiàn)參數(shù)類似標識的情況。
實現(xiàn)函數(shù)已經(jīng)完成了,現(xiàn)在討論的是通用性。。
bydarkst
2012-12-06, 17:30:01
額,好久沒來了,我以為2樓以后就沒人回復了
我是對二樓又補充了下,參數(shù)不用從倒過來寫,也不用-1做標識
對于測試的三個函數(shù)可以,但是仍未處理調(diào)用約定問題
希望相互討論,能繼續(xù)完善它

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

#include <iostream>
#include <vector>
using namespace std;

int StdInvoke(char* lib,char* FucName ,...)
{
va_list ap;
int nResult, nCount, nFunAddr;
vector<int> args;

nCount = ((((*(int*)(*(int*)((int)&lib-4)))&0xff0000) >>16)/4) - 2;

HMODULE hModule = lib?LoadLibrary(lib):GetModuleHandle("kernel32.dll");
nFunAddr = (int)GetProcAddress(hModule, FucName);
va_start(ap, FucName);

for (int i=0; i< nCount; i++)
args.push_back(va_arg(ap, int));

while (!args.empty())
{
i = args.back();
args.pop_back();
__asm push i
}

_asm
{
call [nFunAddr];
mov nResult,eax
}

va_end(ap);
if(lib) FreeLibrary(hModule);

return nResult;
}

int main(int argc, char* argv[])
{
StdInvoke("msvcrt.dll", "printf", "1+2=%d %s\n", 1+2, "haha");
StdInvoke(NULL,"Sleep",3000);

if(IDYES == StdInvoke("user32.dll","MessageBoxA", 0, "content", "title", MB_YESNO))
printf("you pressed yes\n");
else
printf("you pressed no\n");

return 0;
}
pengkui
2012-12-09, 15:12:18
源碼:
#include <windows.h>
#include <stdio.h>

unsigned long __declspec(naked) _calleresp()
{
__asm mov eax, esp
__asm add eax, 4
__asm ret
}

int __declspec(naked) _invoke(const char* libstr, const char* funcstr, ...)
{
__asm {
mov [esp-4],edi
mov edi, [esp]
mov [eax], edi
sub eax, 4
mov [eax], esp
sub eax, 4
mov edi, [esp-4]
mov [eax], edi
mov edi, eax
add edi, 4
sub eax, 4
mov [eax], ecx
add esp, 0x04
mov eax, [esp]
call DWORD ptr[LoadLibraryA]
mov ecx, [esp]
push ecx
push eax
call DWORD ptr[GetProcAddress]
add esp, 0x04
call eax
mov esp, edi
add esp, 4
mov ecx,[esp]
mov esp, [esp-4]
mov [esp], ecx
mov esp, edi
mov edi, [esp-4]
mov ecx, [esp-8]
mov esp, [esp]
ret
}
}

#define invoke(libstr, funcstr, ...) _invoke(libstr, funcstr, __VA_ARGS__, NULL, NULL, NULL, NULL, _calleresp())
#define INVOKE_TEST(libstr, funcstr, ...) printf("TEST:\t%s(%s)\tRET:\t%d\n\n", libstr, funcstr, invoke(libstr, funcstr, __VA_ARGS__))

int main(int argc, char* argv[])
{
INVOKE_TEST("msvcrt.dll", "printf", "看雪論壇-%s\n", "pengkui");
INVOKE_TEST("invokeTestDll.dll", "cdeclFunc");
INVOKE_TEST("invokeTestDll.dll", "stdcallFunc");
return 0;
}
測試dll,.c:
#include <stdio.h>

int __declspec(dllexport) __stdcall stdcallFunc()
{
return printf("%s\n", __FUNCTION__);
}

int __declspec(dllexport) __cdecl cdeclFunc()
{
return printf("%s\n", __FUNCTION__);
}
測試dll, .def
LIBRARY "invokeTestDll"

EXPORTS
stdcallFunc = stdcallFunc
cdeclFunc = cdeclFunc

運行結(jié)果:
E:\pictures\捕獲.png
(圖片上傳不了,不知怎么回事)

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多