java inject and hook

java inject and hook
java inject and hook

注入安卓进程,并hook java世界的方法

说明:

安卓系统的可执行对象有两个世界,一个是Linux Native世界,一个是Java世界.两个世界能够通过jvm产生交互,具体来说就是通过jni技术进行互相干涉.但是在正常情况下,只能在Java世界通过jni调用native方法,二native不能在没有任何java上的支持下干涉java世界.

在一些应用中,我们需要对一个app的java世界进行干涉.再说到linux上的进程注入技术,已不用我多讲,但是传统的linux进程注入技术在安卓上只能进入目标进程的native世界.

于是本教程是要注入别的进程,并hook java世界的java 方法!

条件:

1)手机已root

2)布置好了的ndk环境

3)网友贡献的inject代码

由于安卓上的进程注入网上已经有很多方案了,这里就不列举了,这里就假设读者已经能够将so注入到别的进程并顺利运行了.

首先贴一下这次的目标

package com.example.testar;

import https://www.360docs.net/doc/365444487.html,ng.reflect.Field;

import java.util.HashMap;

import java.util.Map;

import dalvik.system.DexClassLoader;

import https://www.360docs.net/doc/365444487.html,.wifi.WifiInfo;

import https://www.360docs.net/doc/365444487.html,.wifi.WifiManager;

import android.os.Bundle;

import android.app.Activity;

import android.content.Context;

import android.text.GetChars;

import android.util.Log;

import android.view.Menu;

import android.view.View;

import android.widget.Button;

public class MainActivity extends Activity {

private final MapmLoaders =new HashMap();

@Override

protected void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

setContentView(https://www.360docs.net/doc/365444487.html,yout.activity_main);

Button btn =(Button) findViewById(R.id.button1);

btn.setOnClickListener(new View.OnClickListener(){

@Override

public void onClick(View v){

// TODO Auto-generated method stub

WifiManager wifi =(WifiManager)

getSystemService(Context.WIFI_SERVICE);

WifiInfo info = wifi.getConnectionInfo();

System.out.println("Wifi mac :" + info.getMacAddress()); System.out.println("return " + test());

}

});

}

@Override

public boolean onCreateOptionsMenu(Menu menu){

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.main, menu);

return true;

}

private String test(){

return"real";

}

}

我们的目标是上面的test()方法,我们要改变其返回值.

接下来看看我们要注入到目标进程的so.cpp,MethodHooker.cpp

so.cpp:

#include "jni.h"

#include "android_runtime/AndroidRuntime.h"

#include "android/log.h"

#include "stdio.h"

#include "stdlib.h"

#include "MethodHooker.h"

#include

#include "art.h"

#define log(a,b) __android_log_write(ANDROID_LOG_INFO,a,b); // LOG ?:info

#define log_(b) __android_log_write(ANDROID_LOG_INFO,"JNI_LOG_INFO",b); // LOG ?:info

extern"C"void InjectInterface(char*arg){

log_("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");

log_("*-*-*-*-*-* Injected so *-*-*-*-*-*-*-*");

log_("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");

Hook();

log_("*-*-*-*-*-*-*- End -*-*-*-*-*-*-*-*-*-*");

}

extern"C" JNIEXPORT jstring JNICALL

Java_com_example_testar_InjectApplication_test(JNIEnv *env, jclass clazz)

{

Abort_();

return env->NewStringUTF("haha ");;

}

MethodHooker.cpp:

#include "MethodHooker.h"

#include "jni.h"

#include "android_runtime/AndroidRuntime.h"

#include "android/log.h"

#include "stdio.h"

#include "stdlib.h"

#include "native.h"

#include

#define ANDROID_SMP 0

#include "Dalvik.h"

#include "alloc/Alloc.h"

#include "art.h"

#define ALOG(...) __android_log_print(ANDROID_LOG_VERBOSE,

__VA_ARGS__)

static bool g_bAttatedT;

static JavaVM *g_JavaVM;

void init()

{

g_bAttatedT =false;

g_JavaVM = android::AndroidRuntime::getJavaVM();

}

static JNIEnv *GetEnv()

{

int status;

JNIEnv *envnow =NULL;

status = g_JavaVM->GetEnv((void**)&envnow, JNI_VERSION_1_4);

if(status <0)

{

status = g_JavaVM->AttachCurrentThread(&envnow,NULL);

if(status <0)

{

return NULL;

}

g_bAttatedT =true;

}

return envnow;

}

static void DetachCurrent()

{

if(g_bAttatedT)

{

g_JavaVM->DetachCurrentThread();

}

}

static int computeJniArgInfo(const DexProto* proto)

{

const char* sig = dexProtoGetShorty(proto);

int returnType, jniArgInfo;

u4 hints;

/* The first shorty character is the return type. */

switch(*(sig++)){

case'V':

returnType = DALVIK_JNI_RETURN_VOID;

break;

case'F':

returnType = DALVIK_JNI_RETURN_FLOAT;

break;

case'D':

returnType = DALVIK_JNI_RETURN_DOUBLE;

break;

case'J':

returnType = DALVIK_JNI_RETURN_S8;

break;

case'Z':

case'B':

returnType = DALVIK_JNI_RETURN_S1;

break;

case'C':

returnType = DALVIK_JNI_RETURN_U2;

break;

case'S':

returnType = DALVIK_JNI_RETURN_S2;

break;

default:

returnType = DALVIK_JNI_RETURN_S4;

break;

}

jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT;

hints = dvmPlatformInvokeHints(proto);

if(hints & DALVIK_JNI_NO_ARG_INFO){

jniArgInfo |= DALVIK_JNI_NO_ARG_INFO;

}else{

assert((hints & DALVIK_JNI_RETURN_MASK)==0);

jniArgInfo |= hints;

}

return jniArgInfo;

}

int ClearException(JNIEnv *jenv){

jthrowable exception = jenv->ExceptionOccurred();

if(exception !=NULL){

jenv->ExceptionDescribe();

jenv->ExceptionClear();

return true;

}

return false;

}

bool isArt(){

return true;

}

static jclass findAppClass(JNIEnv *jenv,const char*apn){ //oaders

jclass clazzApplicationLoaders =

jenv->FindClass("android/app/ApplicationLoaders");

jthrowable exception = jenv->ExceptionOccurred();

if(ClearException(jenv)){

ALOG("Exception","No class : %s",

"android/app/ApplicationLoaders");

return NULL;

}

jfieldID fieldApplicationLoaders =

jenv->GetStaticFieldID(clazzApplicationLoaders,"gApplicationLoaders", "Landroid/app/ApplicationLoaders;");

if(ClearException(jenv)){

ALOG("Exception","No Static Field :%s","gApplicationLoaders");

return NULL;

}

jobject objApplicationLoaders =

jenv->GetStaticObjectField(clazzApplicationLoaders,fieldApplicationLo aders);

if(ClearException(jenv)){

ALOG("Exception","GetStaticObjectField is failed

[%s","gApplicationLoaders");

return NULL;

}

jfieldID fieldLoaders =

jenv->GetFieldID(clazzApplicationLoaders,"mLoaders","Ljava/util/Map;" );

if(ClearException(jenv)){

ALOG("Exception","No Field :%s","mLoaders");

return NULL;

}

jobject objLoaders =

jenv->GetObjectField(objApplicationLoaders,fieldLoaders);

if(ClearException(jenv)){

ALOG("Exception","No object :%s","mLoaders");

return NULL;

}

//map??alues

jclass clazzHashMap = jenv->GetObjectClass(objLoaders);

jmethodID methodValues =

jenv->GetMethodID(clazzHashMap,"values","()Ljava/util/Collection;"); jobject values = jenv->CallObjectMethod(objLoaders,methodValues);

jclass clazzValues = jenv->GetObjectClass(values);

jmethodID methodToArray =

jenv->GetMethodID(clazzValues,"toArray","()[Ljava/lang/Object;");

if(ClearException(jenv)){

ALOG("Exception","No Method:%s","toArray");

return NULL;

}

jobjectArray classLoaders =

(jobjectArray)jenv->CallObjectMethod(values,methodToArray);

if(ClearException(jenv)){

ALOG("Exception","CallObjectMethod failed :%s","toArray");

return NULL;

}

int size = jenv->GetArrayLength(classLoaders);

for(int i =0; i < size ; i ++){

jobject classLoader =

jenv->GetObjectArrayElement(classLoaders,i);

jclass clazzCL = jenv->GetObjectClass(classLoader);

jmethodID loadClass =

jenv->GetMethodID(clazzCL,"loadClass","(Ljava/lang/String;)Ljava/lang /Class;");

jstring param = jenv->NewStringUTF(apn);

jclass tClazz =

(jclass)jenv->CallObjectMethod(classLoader,loadClass,param);

if(ClearException(jenv)){

ALOG("Exception","No");

continue;

}

return tClazz;

}

ALOG("Exception","No");

return NULL;

}

bool HookDalvikMethod(jmethodID jmethod){

Method *method =(Method*)jmethod;

//!!??О?native

SET_METHOD_FLAG(method, ACC_NATIVE);

int argsSize = dvmComputeMethodArgsSize(method);

if(!dvmIsStaticMethod(method))

argsSize++;

method->registersSize = method->insSize = argsSize;

if(dvmIsNativeMethod(method)){

method->nativeFunc = dvmResolveNativeMethod;

method->jniArgInfo = computeJniArgInfo(&method->prototype);

}

}

bool ClassMethodHook(HookInfo info){

JNIEnv *jenv = GetEnv();

jclass clazzTarget = jenv->FindClass(info.tClazz);

if(ClearException(jenv)){

ALOG("Exception","ClassMethodHook[Can't find class:%s in bootclassloader",info.tClazz);

clazzTarget = findAppClass(jenv,info.tClazz);

if(clazzTarget ==NULL){

ALOG("Exception","%s","Error in findAppClass");

return false;

}

}

jmethodID method =

jenv->GetMethodID(clazzTarget,info.tMethod,info.tMeihodSig);

if(method==NULL){

ALOG("Exception","ClassMethodHook[Can't find

method:%s",info.tMethod);

return false;

}

if(isArt()){

HookArtMethod(jenv,method);

}else{

HookDalvikMethod(method);

}

JNINativeMethod gMethod[]={

{info.tMethod, info.tMeihodSig, info.handleFunc}, };

//func?NULL??А?

if(info.handleFunc !=NULL){

//!!??????ative

if(jenv->RegisterNatives(clazzTarget, gMethod,1)<0){ ALOG("RegisterNatives","err");

return false;

}

}

DetachCurrent();

return true;

}

int Hook(){

init();

void* handle = dlopen("/data/local/libTest.so",RTLD_NOW);

const char*dlopen_error = dlerror();

if(!handle){

ALOG("Error","cannt load plugin :%s",dlopen_error);

return-1;

}

SetupFunc setup =(SetupFunc)dlsym(handle,"getpHookInfo");

const char*dlsym_error = dlerror();

if(dlsym_error){

ALOG("Error","Cannot load symbol 'getpHookInfo' :%s", dlsym_error);

dlclose(handle);

return1;

}

HookInfo *hookInfo;

setup(&hookInfo);

ALOG("LOG","Target Class:%s",hookInfo[0].tClazz);

ALOG("LOG","Target Method:%s",hookInfo[0].tMethod);

ClassMethodHook(hookInfo[0]);

}

以下是我们想要的目标进程java世界执行的我们自定义的代码

libTest.so

#include "native.h"

#include

#include "stdio.h"

#include "stdlib.h"

#include "MethodHooker.h"

#define log(a,b) __android_log_print(ANDROID_LOG_VERBOSE,a,b); // LOG ?:info

#define log_(b)

__android_log_print(ANDROID_LOG_VERBOSE,"JNI_LOG_INFO",b); // LOG ?:info

int getpHookInfo(HookInfo** pInfo);

JNIEXPORT void JNICALL

Java_com_example_testar_InjectClassloader_hookMethodNative

(JNIEnv * jenv, jobject jboj, jobject jobj, jclass jclazz, jint slot) {

//log("TestAE","start Inject other process");

}

JNIEXPORT jstring JNICALL test(JNIEnv *env, jclass clazz)

{

//__android_log_print(ANDROID_LOG_VERBOSE, "tag", "call

in java");

return(*env)->NewStringUTF(env,"haha ");;

}

HookInfo hookInfos[]={

{"android/net/wifi/WifiInfo","getMacAddress","()Ljava/lang/String;",( void*)test},

//{"com/example/testar/MainActivity","test","()Ljava/lang/String;",(v oid*)test},

//{"android/app/ApplicationLoaders","getText","()Ljava/lang/CharSeque nce;",(void*)test},

};

int getpHookInfo(HookInfo** pInfo){

*pInfo = hookInfos;

return sizeof(hookInfos)/sizeof(hookInfos[0]);

}

程序大致的流程是这样的,首先将so.so注入到目标进程,执行里面的Hook()函数,然后

Hook()加载libTest.so,获取里面定义的Hook信息.接着用ClassMethodHook挂钩java 世界的方法.

关键一,从native世界进入java世界.熟悉jni编程的都知道,java到native的桥梁是JNIEnv,我们只要获得一个JNIEnv就能进入到java世界了.突破点就在AndroidRuntime,android::AndroidRuntime::getJavaVM();这个静态方法能够获取一个JavaVM, JavaVM->GetEnv方法能够获得一个JNIEnv了.JNIEnv是和线程相关的,

使用前一定记得将其附加到当前进程,也要在适当的时候将其销毁.

关键二,怎么影响内存里的java代码,这个情况替换内存是不现实的,但是可以取巧.我们知道java代码里将一个方法声明为native方法时,对此函数的调用就会到native世界里找.我们何不在运行时将一个不是native的方法修改成native方法呢?这是可以做到的,看着段代码

bool HookDalvikMethod(jmethodID jmethod){

Method *method =(Method*)jmethod;

//!!??О?native

SET_METHOD_FLAG(method, ACC_NATIVE);

int argsSize = dvmComputeMethodArgsSize(method);

if(!dvmIsStaticMethod(method))

argsSize++;

method->registersSize = method->insSize = argsSize;

if(dvmIsNativeMethod(method)){

method->nativeFunc = dvmResolveNativeMethod;

method->jniArgInfo = computeJniArgInfo(&method->prototype);

}

}

Jni反射调用java方法时要用到一个jmethodID指针,这个指针在Dalvik里其实就是Method类,通过修改这个类的一些属性就可以实现在运行时将一个方法修改成native方法. SET_METHOD_FLAG(method, ACC_NATIVE);就是这么做的,其后面的代码就是设定

native函数的参数占用内存大小统计.

也许你发现了,虽然将其修改成一个native方法了,但是这个方法对应的native代码在那里呢?这样做

//?!!??????ative

if(jenv->RegisterNatives(clazzTarget, gMethod,1)<0){

ALOG("RegisterNatives","err");

return false;

}

可以将一个native函数绑定到一个java的native方法

这样就能够实现开始的目标了!

我这里讲得是有点粗略了,但是这个技术牵涉到的知识太多了,主要是给老鸟参考的,小菜

们拿来用用就好,要是要讲得小菜们都能明白,就不知要讲到何年何月了.还有就是上面的art

环境的代码是跑不起来的,等我后面有空完善了再发一次吧!

本教程仅供学习交流用途,请勿用于非法用途!

希望老鸟勿笑,小鸟勿喷!谢谢观赏!

测试代码猛击这里:https://www.360docs.net/doc/365444487.html,/s/1nt9GBsX

驱动程序

linux 驱动程序设计实验 一实验目的 1.了解LINUX操作系统中的设备驱动程序的组成 2.编写简单的字符设备驱动程序并进行测试 3.编写简单的块设备驱动程序并进行测试 4.理解LINUX操作系统的设备管理机制 二准备知识 1. LINUX下驱动程序基础知识 Linux抽象了对硬件的处理,所有的硬件设备都可以像普通文件一样来看待:它们可以使用和操作文件相同的、标准的系统调用接口来完成打开、关闭、读写和I/O控制操作,而驱动程序的主要任务也就是要实现这些系统调用函数。在Linux操作系统下有两类主要的设备文件:一类是字符设备,另一类则是块设备。字符设备是以字节为单位逐个进行I/O操作的设备,在对字符设备发出读写请求时,实际的硬件I/O紧接着就发生了,一般来说字符设备中的缓存是可有可无的,而且也不支持随机访问。块设备则是利用一块系统内存作为缓冲区,当用户进程对设备进行读写请求时,驱动程序先查看缓冲区中的内容,如果缓冲区中的数据能满足用户的要求就返回相应的数据,否则就调用相应的请求函数来进行实际的I/O操作。块设备主要是针对磁盘等慢速设备设计的,其目的是避免耗费过多的CPU时间来等待操作的完成。一般说来,PCI卡通常都属于字符设备。 我们常见的驱动程序就是作为内核模块动态加载的,比如声卡驱动和网卡驱动等,这些驱动程序源码可以修改到内核中,也可以把他们编译成模块形势,在需要的时候动态加载. 而Linux最基础的驱动,如CPU、PCI总线、TCP/IP协议、APM (高级电源管理)、VFS等驱动程序则编译在内核文件中。有时也把内核模块就叫做驱动程序,只不过驱动的内容不一定是硬件罢了,比如ext3文件系统的驱动。当我们加载了设备驱动模块后,应该怎样访问这些设备呢?Linux是一种类Unix系统,Unix的一个基本特点是“一切皆为文件”,它抽象了设备的处理,将所有的硬件设备都像普通文件一样看待,也就是说硬件可以跟普通文件一样来打开、关闭和读写。 系统中的设备都用一个设备特殊文件代表,叫做设备文件,设备文件又分为Block (块)型设备文件、Character(字符)型设备文件和Socket (网络插件)型设备文件。Block设备文件常常指定哪些需要以块(如512字节)的方式写入的设备,比如IDE硬盘、SCSI硬盘、光驱等。而Character型设备文件常指定直接读写,没有缓冲区的设备,比如并口、虚拟控制台等。Socket(网络插件)型设备文件指定的是网络设备访问的BSD socket 接口。 设备文件都放在/dev目录下,比如硬盘就是用/dev/hd*来表示,/dev/hda表示第一个IDE 接口的主设备,/dev/hda1表示第一个硬盘上的第一个分区;而/dev/hdc 表示第二个IDE接口的主设备。对于Block和Character型设备,使用主(Major)和辅(minor)设备编号来描述设备。主设备编号来表示某种驱动程序,同一个设备驱动程序模块所控制的所有设备都有一

通过DLL劫持技术HookAPI

DLL劫持技术 当一个可执行文件运行时,Windows加载器将可执行模块映射到进程的地址空间中,加载器分析可执行模块的输入表,并设法找出任何需要的DLL,并将它们映射到进程的地址空间中。 由于输入表中只包含DLL名而没有它的路径名,因此加载程序必须在磁盘上搜索DLL文件。首先会尝试从当前程序所在的目录加载DLL,如果没找到,则在Windows系统目录中查找,最后是在环境变量中列出的各个目录下查找。利用这个特点,先伪造一个系统同名的DLL,提供同样的输出表,每个输出函数转向真正的系统DLL。程序调用系统DLL时会先调用当前目录下伪造的DLL,完成相关功能后,再跳到系统DLL同名函数里执行,如图18.3所示。这个过程用个形象的词来描述就是系统DLL被劫持(hijack)了。 图18.3 DLL劫持技术演示 利用这种方法取得控制权后,可以对主程序进行补丁。此种方法只对除kernel32.dll、ntdll.dll等核心系统库以外的DLL有效,如网络应用程序的ws2_32.dll、游戏程序中的d3d8.dll,还有大部分应用程序都调用的lpk.dll,这些DLL都可被劫持。 利用第5章5.6.2节提供的CrackMeNet.exe来演示一下如何利用劫持技术制作补丁,目标文件用Themida v1.9.2.0加壳保护。 1.补丁地址 去除这个CrackMe网络验证方法参考第5章5.6.2节,将相关补丁代码存放到函数PatchProcess()里。例如将401496h改成:00401496 EB 29 jmp short 004014C1

补丁编程实现就是: unsigned char p401496[2] = {0xEB, 0x29}; WriteProcessMemory(hProcess,(LPVOID)0x401496, p401496, 2, NULL); p401496这个数组的数据格式,可以用OllyDbg插件获得,或十六进制工具转换。例如Hex Workshop打开文件,执行菜单“Edit/Copy As/Source”即可得到相应的代码格式。 2.构建输出函数 查看实例CrackMeNet.exe输入表,会发现名称为“ws2_32.dll”的DLL,因此构造一个同名的DLL来完成补丁任务。伪造的ws2_32.dll 有着真实ws2_32.dll一样的输出函数,完整源码见光盘映像文件。实现时,可以利用DLL模块中的函数转发器来实现这个目标,其会将对一个函数的调用转至另一个DLL中的另一个函数。可以这样使用一个pragma指令: #pragma comment(linker, "/EXPORT:SomeFunc=DllWork.someOtherFunc") 这个pragma告诉链接程序,被编译的DLL应该输出一个名叫SomeFunc的函数。但是SomeFunc函数的实现实际上位于另一个名叫SomeOtherFunc的函数中,该函数包含在称为DllWork. dll的模块中。 如果要达到劫持DLL的目的,生成的DLL输出函数必须与目标DLL输出函数名一样。本例可以这样构造pragma指令: #pragma comment(linker, "/EXPORT:WSAStartup=_MemCode_WSAStartup,@115") 编译后的DLL,会有与ws2_32.dll同名的一个输出函数WSAStartup,实际操作时,必须为想要转发的每个函数创建一个单独的pragma 代码行,读者可以用工具AheadLib或用其他办法,将ws2_32.dll输出函数转换成相应的pragma指令。 当应用程序调用伪装ws2_32.dll的输出函数时,必须将其转到系统ws2_32.dll中,这部分的代码自己实现。例如,WSAStartup输出函数构造如下:

SQLSERVER2008开启远程数据库访问图解

SQL SERVER2008开启远程数据库访问图解moon.翘楚 2012-02-19 8:52 转载自zhangcheng1 最终编辑zhangcheng1 tag:sql server2008远程数据库,远程连sql,IP远程连SQL SERVER,1433端口映射 这篇文章不错,我试验了确实可以,moon.翘楚在这里再进行一下图文增补,让大家更加明白。 讲解SQL Server 2008开启远程连接 作者:blue1000出处:IT专家网论坛2010-06-23 07:00 sql server 2008默认是不允许远程连接的,sa帐户默认禁用的,如果想要在本地用SSMS连接远程服务器上的SQL Server 2008,需要做两个部分的配置: sql server 2008默认是不允许远程连接的,sa帐户默认禁用的,如果想要在本地用SSMS连接远程服务器上的SQL Server 2008,需要做两个部分的配置: 1,SQL Server Management Studio Express(简写SSMS) 2,SQL Server 配置管理器/SQL Server Configuration Manager(简写SSCM) 有两点要注意: 1,2005的外围应用配置器在2008中换了地方 2,有些设置生效需要重启一下SQL Server step 1: 打开SSMS,用windows身份连接数据库,登录后,右键选择“属性” step 2: 左侧选择“安全性”,选中右侧的“SQL Server 和 Windows 身份验证模式”以启用混合登录模式 step 3: 选择“连接”,勾选“允许远程连接此服务器”,然后点“确定” step 4: 展开“安全性”->“登录名”->“sa”,右键选择“属性” step 5: 左侧选择“常规”,右侧选择“SQL Server 身份验证”,并设置密码 step 6: 选择“状态”,选中“启用”,点击“确定” step 7: 右击数据库选择“方面”

网络连接数据库

package day01; import java.sql.Connection; import java.sql.DriverManager; public class JDBCConnection { public static void main(String[] args) throws Exception { //注册驱动 Class.forName("oracle.jdbc.driver.OracleDriver"); //连接 Connection conn=DriverManager.getConnection( "jdbc:oracle:thin:@192.168.7.134:1521:orcl", "system","tarena"); System.out.println(conn); } } NetCTOSS 电信运营支撑系统 资费管理模块资费: cost/fee 主要功能: 针对资费信息的CURD(增删改查)操作. 常见的企业级应用 OSS : 运营支撑系统 CRM: 客户关系管理 ERP: 企业资源规划 技术: JavaEE开发、JavaWeb开发 JavaSE JavaEE Web技术数据库 常见的软件架构体系: (1) C/S client/server客户端/服务架构 client 需要单独安装客户端软件QQ serve 服务器端软件 优点: 客户端可以单独开发,功能和界面可以非常丰富 缺点: 软件的升级成本高 (2)B/S browser/server浏览器/服务架构 是一种特殊的c/s结构 client: 浏览器Browser IE/Firefox/chrome server: 服务器Web服务器 http协议超文本传输协议简单、无状态的协议请求request和应答response

驱动入口函数

这个驱动程序包含了三个函数:DriverEntry、HelloDDKUnload和HelloDDKDispatchRoutine。其中DriverEntry是驱动程序的入口函数,相当于C/C++程序的main函数,HelloDDKUnload函数是驱动卸载函数。而HelloDDKDispatchRuntine则是IRP的派遣函数,因为驱动程序主要是处理IO 请求,而IO请求大多是在派遣函数中处理的。 先来看看这个驱动程序的第一个函数:DriverEntry /**************************************************************** * 函数名称:DriverEntry * 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象 * 参数列表: pDriverObject:从I/O管理器中传来的驱动对象 pRegistryPath:驱动程序在注册表中的路径 * 返回值:返回初始化驱动状态 ****************************************************************/ #pragma INITCODE extern "C" NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath ) { NTSTATUS status; KdPrint( ( "Enter DriverEntry!\n" ) ); //注册其它驱动调用函数入口 pDriverObject->DriverUnload = ( PDRIVER_UNLOAD ) HelloDDKUnload; pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine; pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine; pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine; pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine; //创建驱动设备对象 status = CreateDeivce( pDriverObject ); KdPrint( ( "DriverEntry end!\n" ) ); return status; } 这个函数的第一句代码是一个#pragma预处理指令: #pragma INITCODE

用PLSQL远程连接Oracle数据库

PL/SQL Developer 远程连接Oracle数据库 1、配置服务器tnsnames.ora文件,如果本机上没有安装oracle,可以从安 装了oracle的机上拷贝一个(tnsnames.ora文件)放在指定目录下,因为我已安装oracle,所以直接配置该文件。 # tnsnames.ora Network Configuration File: D:\Oracle11g\product\11.2.0\dbhome_1\network\admin\tnsnames.ora # Generated by Oracle configuration tools. LISTENER_ORCL = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) ORACLR_CONNECTION_DATA = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) ) (CONNECT_DATA = (SID = CLRExtProc) (PRESENTATION = RO) ) ) ORCL = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.25.224)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orcl) ) ) orcl为远程Oracle数据库的实例名,IP地址和端口也要配置正确。 2、配置完成后,Oracle客户端应该可以连接到远程Oracle 数据库上。

数据库系统的访问

第7章数据库系统的访问 对于那些相对独立的软件供应商而言,经常要为每一个DBMS编写一个版本的应用程序,或者为每个要访问的DBMS编写针对DBMS的代码。这就意味着,大量的资源都耗在了编写和维护DB的访问上,更不用说应用程序了。此时应用程序的评价标准不再是质量,而是它能否在给定的DBMS中访问数据库。 这就需要开放的数据库连接,就是人们需要用一种新的方法来访问不同的数据库。为此,在C/S,B/S系统中必须广泛使用访问接口技术,以隐藏各种复杂性,屏蔽各种系统之间的差异。常见的数据库访问接口的技术有固有调用、ODBC、JDBC、OLE DB、DAO、ADO、https://www.360docs.net/doc/365444487.html, 以及基于XML的数据库访问等几种流行的方式。这其中以ODBC技术和JDBC技术应用最广泛,也是目前最为优秀的访问接口方式。 本章主要对几种常见的数据库访问技术(如固有调用、ODBC、JDBC、OLE DB、DAO、ADO、https://www.360docs.net/doc/365444487.html,以及基于XML的数据库访问等)进行介绍。 7.1 数据库的访问接口 所谓访问接口是指分布式环境中保证操作系统、通信协议、数据库等之间进行对话、互操作的软件系统。 访问接口的作用是保证网络中各部件(软件和硬件)之间透明地连接,即隐藏网络部件的异构性,尤其保证不同网络、不同DBMS和某些访问语言的透明性,即下面三个透明性。 ⑴网络透明性:能支持所有类型的网络。 ⑵服务器透明性:不管服务器上的DBMS是何种型号(ORACLE、SYBASE、DB2等),一个好的访问接口都能通过标准的SQL语言与不同DBMS上的SQL语言连接起来。 ⑶语言透明性:客户机可用任何开发语言进行发送请求和接受回答,被调用的功能应该像语言那样也是独立的。 应用系统访问数据库的接口方式有多种,本节介绍固有调用、ODBC和JDBC。 7.1.1 固有调用 每个数据库引擎都带有自己的包含用于访问数据库的APl函数的动态链接库DLL,应用程序可利用它存取和操纵数据库中的数据。如果应用程序直接调用这些动态链接库,就说它执行的是“固有调用”,因为该调用对于特定的数据库产品来说是“固有” (专用)的。 固有调用接口的优点是执行效率高,由于是“固有”,编程实现较简单。但它的缺点也是很严重的:不具通用性。对于不同的数据库引擎,应用程序必须连接和调用不同的专用的动态链接库,这对于网络数据库系统的应用是极不方便的。 7.1.2 ODBC ODBC是“开放数据库互连”(Open Database Connectivity)的简称。ODBC是Microsoft 公司提出的、当前被业界广泛接受的应用程序通用编程接口(API)标准,它以X/Open和ISO/IEC的调用级接口(CLI)规范为基础,用于对数据库的访问。我们可以用如下图示来说明ODBC概念。

数据库访问技术

7.2 数据库访问技术 访问数据库中的数据对象时,一般可采用两种访问方式:一是登录用户直接借助DBMS 的数据操纵工具,通过图形或SQL命令接口联机访问;另外一种为程序代码通过应用程序编程接口(Application Programming Interface,API)进行数据库连接验证以及数据操作。两种数据库访问方式,可以抽象为图7.5的层次结构,从中可见中间的接口组件是数据库访问的桥梁与核心,本节主要就该部分的通用接口技术(即API访问方式)部分进行介绍。 图7.5 数据库访问结构示意 根据底层数据操作模式的差异,数据库接口可简单分为:本地(Local)数据库接口和客户机/服务器(Client/Server)数据库接口。 1.本地数据库接口 通过DBMS将用户数据请求转换成为简单的磁盘访问命令,并交由操作系统的文件管理系统执行;然后DBMS从文件管理系统得到数据响应并加以处理。由于DBMS数据文件组织结构的差异,本地型DBMS只能够读取特定的数据源。 2.客户机/服务器数据库接口 数据处理工作分散到工作站和服务器上处理。工作站通过特定的数据库通信API,把数据访问请求传给相应的服务器的后端数据驱动程序。由于不同客户机/服务器数据库管理系统通信机制的差异,异构数据库之间也难以实现透明通信互访。 因此,仅依靠特定DBMS提供的数据库访问接口难以支撑透明的、通用的异构数据库访问。后台数据库管理系统的变更或升级,需要程序员对特定API的重新学习,以及对应用程序代码的改写;而市场上DBMS产品众多,必将进一步加大系统开发人员的学习和维护压力,应用程序与数据源间的独立性难以真正实现。为此,建立更为通用的数据访问技术规范,为程序用户提供一套完整、统一的数据库访问接口,得到了数据库业界广泛认同与支持,并由此产生了众多成熟的数据库访问接口应用技术规范。 到目前为止,主流的数据库访问技术包括ODBC、MFC ADO、RDO、OLE DB、ADO、https://www.360docs.net/doc/365444487.html,以及JDBC等通用技术标准。这些通用数据库访问技术的出现与发展大大降低了数据库系统开发与维护门槛,改善了数据库系统的移植性、扩展性,极大推动了数据库技术的发展与普及。下面就主流数据库访问技术发展与演化进行介绍。

字符设备驱动相关函数及数据结构简介

1.设备号 分为主次设备号,看上去像是两个号码,但在内核中用dev_t()一种结构表示,同时不应该自己去假设赋值设备号,而是使用宏()来取得. MAJOR(dev_t dev); MINOR(dev_t dev); 即使你有确定的主,次设备号也要用 dev=MKDEV(int major, int minor); 1.1分配设备号 静态分配 int register_chrdev_region(dev_t first, unsigned int count, char *name); first 是你要分配的起始设备编号. first 的次编号部分常常是0, 但是没有要求是那个效果. count 是你请求的连续设备编号的总数. 注意, 如果count 太大, 你要求的范围可能溢出到下一个次编号; 但是只要你要求的编号范围可用, 一切都仍然会正确工作. name 是应当连接到这个编号范围的设备的名子; 它会出现在/proc/devices 和sysfs 中 动态分配 int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name); dev 是一个只输出的参数, 它在函数成功完成时持有你的分配范围的第一个数. fisetminor 应当是请求的第一个要用的次编号; 它常常是0. count 和name 参数如同给request_chrdev_region 的一样 >>>应该始终使用动态分配,但最好为定制设备号留有接口,以参数形式,以name_major=0做为默认值,可能 的操作如下: if(scull_major){ dev = MKDEV(scull_major, scull_minor); result = register_chrdev_region(dev, scull_nr_devs,"scull"); }else{ result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs,"scull"); scull_major = MAJOR(dev); } if(result < 0){ printk(KERN_WARNING "scull: can't get major %d\n", scull_major); return result; } 1.2释放设备号 void unregister_chrdev_region(dev_t first, unsigned int count);

VB外挂之HOOK技术的最详细教程

vb外挂之HOOK技术终极详细解说 By:史上最大小强 很多学习vb的人都想学习外挂及hook,我在网上也找到了一段程序,后台键盘记录外挂,其实网上大多数流传的HOOK代码都跟这段代码几乎一个出处。网上有关于这些代码的解释,但是关键部分根本就没解释,等于没说。 下面的程序解释得很详细。有的地方全属个人看法,不过还是值得一看。不对的地方欢迎大家指出。当然,高手勿笑。 好吧,正式我们的hook学习。 Hook并不神秘,它说到底就是通过调用API函数在消息队列中安装钩子,实现截获消息,处理消息的功能。在这里,我浅浅的讲讲windows的消息机制。比如,我们按键盘的某个键时,系统就会生成一个消息到系统的消息队列,系统再发送到应用程序消息队列中,windows有不同的消息队列。对于键盘钩子,是安装在系统的消息队列中。 看程序:(以下程序在模块中,呵呵,工程-----添加模块) Option Explicit ‘强制性变量声明,不允许出现未声明的变量。呵呵,都懂!! Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer ‘Getkeystate是api函数,顾名思义,获取某个键的状态,参数nvirtkey就是某个键的虚拟键键码,不同的系统虚拟键码不同。比如vbkeycontrol或者vbkeyshift就可以作为参数。 返回值是16位的,如开关键打开,则位0设为1(开关键包括CapsLock,NumLock,ScrollLock);如某个键当时正处于按下状态,则位15为1;如已经抬起,则为0。数据在储存器中,最高位为1时是负数,为0时是正数。 Public Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long ‘Setwindowshookex,就是建立钩子的函数,最主要的的函数。 参数: Idhoook:要建立什么类型的hook。 有以下类型: WH_MSGFILTER = -1; 线程级; 截获用户与控件交互的消息 WH_JOURNALRECORD = 0; 系统级; 记录所有消息队列从消息队列送出的输入消息, 在消息从队列中清除时发生; 可用于宏记录 WH_JOURNALPLAYBACK = 1; 系统级; 回放由WH_JOURNALRECORD 记录的消息, 也就是将这些消息重新送入消息队列 WH_KEYBOARD = 2; 系统级或线程级; 截获键盘消息 WH_GETMESSAGE = 3; 系统级或线程级; 截获从消息队列送出的消息 WH_CALLWNDPROC = 4; 系统级或线程级; 截获发送到目标窗口的消息, 在SendMessage 调用时发生 WH_CBT = 5; 系统级或线程级; 截获系统基本消息, 譬如: 窗口的创建、激活、关闭、最大最小化、移动等等 WH_SYSMSGFILTER = 6; 系统级; 截获系统范围内用户与控件交互的消息

SQL2000数据库实现远程连接

SQL 2000数据库怎么实现远程连接 SQL Server 2000无论是个人版、企业版还是标准版,只要细版本在8.00.1760以下,均不提供远程数据库连接,即使服务器端工具和客户端工具的设置均有TCP/IP设置和数据库连接属性也设置了RPC远程连接,仍然不能实现远程连接。该怎么解决呢? 解决方案如下: 首先,需要打SP4补丁,该补丁包含了以前sp1、2、3的补丁,安装此补丁后一般要重新启动计算机,再进行远程连接就可以了,如再企业管理器可远程注册服务器、查询分析可连接远程服务器、ODBC可连接远程服务器。 要点: 1.确认服务器端SQL服务端口号是否为:1433 2.如果不是1433,配置客户端 3.建立服务器端登录帐号,确保角色及管理数据库 一、查看服务器端情况 1. 看ping 服务器IP能否ping通。 这个实际上是看和远程sql server 服务器的物理连接是否存在。如果不行,请检查网络,查看配置,当然得确保远程sql server 服务器的IP拼写正确。 2. 在Dos或命令行下输入telnet 服务器IP 端口,看能否连通。 如telnet 202.114.100.100 1433 通常端口值是1433,因为1433是sql server 的对于Tcp/IP的默认侦听端口。如果有问题,通常这一步会出问题。通常的提示是“……无法打开连接,连接失败"。 如果这一步有问题,应该检查以下选项。 1) 检查远程服务器是否启动了sql server 服务。如果没有,则启动。 2) 检查sql server服务器端有没启用Tcp/IP协议,因为远程连接(通过因特网)需要靠这个协议。检查方法是,在服务器上打开开始菜单->程序->Microsoft SQL Server->服务器网络实用工具,看启用的协议里是否有tcp/ip协议,如果没有,则启用它。 3) 检查服务器的tcp/ip端口是否配置为1433端口。仍然在服务器网络实用工具里查看启用协议里面的tcp/ip的属性,确保默认端口为1433,并且隐藏服务器复选框没有勾上。 事实上,如果默认端口被修改,也是可以的,但是在客户端做telnet测试时,写服务器端口号时必须与服务器配置的端口号保持一致。如果隐藏sql server服务器复选框被勾选,则意味着客户端无法通过枚举服务器来看到这台服务器,起到了保护的作用,但不影响连接,但是Tcp/ip协议的默认端口将被隐式修改为2433,在客户端连接时必须作相应的改变(具体方式见二:设置客户端网络实用工具)。

Labview中远程数据库访问技术

摘要:介绍了在Labview中应用ADO技术访问本地和远程数据库的方案。对在局域网中以网络 共享方式访问远程Access数据库进行了详细介绍,最后给出了应用该方法开发的一个实例。关 键词:LabviewADO远程数据库引言Labview是美国NI公司开发的一种图形化编程语言,其主 要用于数据采集、仪器控制、过程监控等领域。Labview具有丰富的采集与分析函数库,在Labview环境下可以方便快捷地开发监控系统软件。现代监控系统一般构建于局域网内,且 摘要:介绍了在Labview中应用ADO技术访问本地和远程数据库的方案。对在局域网中以网络共享方式访问远程Access数据库进行了详细介绍,最后给出了应用 该方法开发的一个实例。 关键词:Labview ADO 远程数据库 引言 Labview 是美国NI公司开发的一种图形化编程语言,其主要用于数据采集、仪器控制、过程监控等领域。Labview具有丰富的采集与分析函数库,在Labview 环境下可以方便快捷地开发监控系统软件。现代监控系统一般构建于局域网内,且监控系统自身也是企业生产管理系统的一个子系统,因此不可避免地要访问本地或远程数据库。Labview开发版中并没有提供直接与通用数据库接口的工具,但可以 通过以下方法解决:购买NI公司开发的附加软件工具包;利用其它语言如VC++编写DLL访问数据库;利用ADO控件访问数据库。[1]Labview支持Activex控件,与其它方法相比基于ADO技术构建本地或远程数据库访问接口不失为一种简单而又经济 的方法。 1 ADO技术简介 ADO(Activex Data Objects)是Microsot为OLE DB设计的应用层接口,它为一致的数据访问接口提供了良好的扩展性而不局限于单一的数据源。ADO接口编程模型中包括连接(connection)、命令(command)、参数(parameter)、 记录集(recordset)、字段(field)、错误(error)、属性(property)、集合(collection)、事件(event)等元素。其中connection、command、recordset是三个主体对象,parameters、fields、errors、properties、是四个集合对象。ADO的一般操作方式为:1 连接到数据源;2 指定访问数据源的命令;3 执行命令;4 将命令执行后产生的结果保存在缓存中;5 更新数据源。ADO接口继承了OLE DB的高速性,可以高速访 问本地或远程的数据源。 2在Labview 中使用ADO接口 在Labview 中使用ADO接口访问数据库一般包括以下几个步骤:建立ADO控件;连接到数据源;生成SQL命令;执行命令;关闭连接。具体步骤如图1 所示。 2.1建立ADO控件 在前面板控件模板中选择Activex子模板单击Automation Refnum项,右键单击Select Activex Class的Browse从类型库中选择 Microsoft Activex Data Objects 2.7 library Version 2.7,之后可以向框图程序中加 入connection、command、recordset等对象。 2.2连接到数据源 首先在Diagram中单击鼠标右键,从Function模板选择communication 子模板,从中选择Activex项的Automation Open 与ADODB_Connection相连即 可打开连接。接着同样从communication子模板的Activex项中选择 Invoke node (方法节点)并与Automation Open 相连,在其上单击右键选择methods项的Open方法即出现图1中所示的节点。其中“Open”表示该节点为打开“连接对象”,“ConnectionString”是连接到数据源的字符串,“UserID”和“Password”

第七讲 VB访问SQL Server2000数据库的方法

第七讲 VB访问SQL Server2000数据库的方法 一、ODBC数据源设置 1、ODBC简介 ODBC Open DatabaseConnectivity开放式数据库互连)是Mircosoft公司有关数据库的一个组成部分,它建立了一组规范,并提供了一组对数据库访问的标准API Application应用程序编程接口)。这些API利用SQL来完成大部分的任务。ODBC本身提供对SQL语言的支持,用户可以直接将SQL送给ODBC一个基于ODBC的应用程序对数据库操作不依赖于任何DBMS,不直接与DBMS打交道,所有数据库操作由ODBC驱动程序完成。 2、ODBC数据源的创建(建立ODBC数据源) 前台系统Windows 2000 professional系统,后台Windows 2000 Server系统。以Windows 2000 professional为例: (1)单击“开始”/设置/控制面板/管理工具/数据源ODBC,打开“ODBC数据源管理器”,选择“用户DSN or 系统DSN”,单击【添加】按钮,打开“创建用户数据源”对话框,选择“SQL Server”,单击【完成】按钮。

(2)打开“创建新的数据源到SQL Server”窗口: ○1你想用什么名称命名数据源:在名称框中输入xn。 ○2服务器:为网络中数据库服务器(默认是本地服务器Local,可选远程服务器IP)。 ○3登陆ID:xn密码:xn(取决于安装SQL时所指定的密码)。特别注意此处为确保数据库安全起见,数据库管理员可以给用户指定一个用户名及密码。这里为简便起见使用管理员用户名及密码。 ○4更改数据库为:aa(所要使用的数据库)。

远程访问数据库

远程访问数据库 对于oracle数据库,可以通过建立dblink的方式,在一个数据库中访问获取另一个数据库的数据,具体实现方式如下: 1.建立DATABASE LINK: 在本机数据库中执行如下语句: Create public database link ERPDATABASE–远程数据库连接名 Connectto apps identifiedby apps Using '(DESCRIPTION = (ADDRESS_LIST= (ADDRESS = (PROTOCOL = TCP) (HOST = 192.168.0.100) (PORT = 1521) ) ) (CONNECT_DATA = (SERVICE_NAME = ERPTEST) ) ) ' ; 蓝色部分可以从数据库安装目录\product\10.2.0\db_1\network\ADMIN的路径下找到,拷贝tnsnames.ora文件中的对应信息。 以上连接信息可以用oracle客户端的Net Manager工具生成:

2.查看数据 成功之后,可以在本机数据库中查看ERPTEST数据库的数据: 其中需要注意的有: 1)ygfm为数据库用户名,因为dblink的连接信息中使用的apps用户是数据库dba,所以可以方位ygfm的数据,这里要注意的是apps需要有ygfm的访问权限。 2)注意需要使用’ @ERPDATABASE’标识远程数据库。 3.建立同义词 可以建立同义词减少输入: 执行以下语句: Create synonym ygfm_analyse_base for ygfm.ygfm_analyse_base@ERPDATABASE; 查询: select * from ygfm_analyse_base; 需要注意的是:这里建立的DATABASE LINK 不同于tnsnames.ora文件中的连接信息,这里是在数据库中保存连接信息,而tnsnames.ora文件中的连接信息是在数据库层面之上的。

数据库访问技术简介

数据库访问技术简介 数据库中的数据存放在数据库文件中,我们要从数据库文件中获取数据,先要连接并登陆到存放数据库的服务器。一般来说,访问数据库中的数据有两种方式:一是通过DBMS (Data Base Management System,数据库管理系统)提供的数据库操作工具来访问,如通过SQL Server 2000的查询设计器来提交查询,或者通过SQL Server 2000的企业管理工具来访问。这种方式比较适合DBA对数据库进行管理;二是通过API(Application Programming Interface, 应用编程接口)来访问数据库,这种方式适合在应用程序中访问数据库。 在数据库发展的初期,各个开发商为自己的数据库设计了各自不同的DBMS,因此不同类型的数据库之间数据交换非常困难。为了解决这个问题,Microsoft提出了ODBC(Open Data Base Connectivity,开放数据库互连)技术,试图建立一种统一的应用程序访问数据库接口,使开发人员无需了解程序内部结构就可以访问数据库。 1、Microsoft提出的系列数据库访问技术 1.1、ODBC ODBC是微软公司开放服务结构中有关数据库的一个组成部分,它建立了一组规范,并提供了一组对数据库访问的标准API。应用程序可以使用所提供的API来访问任何提供了ODBC驱动程序的数据库。ODBC规范为应用程序提供了一套高层调用接口规范和基于动态链接的运行支持环境。ODBC已经成为一种标准,目前所有的关系数据库都提供了ODBC 驱动程序,使用ODBC开发的应用程序具有很好的适应性和可移植性,并且具有同时访问多种数据库系统的能力。这使得ODBC的应用非常广泛,基本可用于所有的关系数据库。 要使用ODBC,先要了解以下概念:ODBC驱动管理器、ODBC驱动程序、数据源。它们都是ODBC的组件。ODBC组件之间的关系如图1所示。

驱动名词解释

驱动 NTSTATUS NTSTATUS 是被定义为32位的无符号长整型。在驱动程序开发中,人们习惯用NTSTATUS 返回状态。其中0~0X7FFFFFFF,被认为是正确的状态,而0X80000000~0XFFFFFFFF被认为是错误的状态。 有一个非常有用的宏-----NT_SUCCESS,用来检测状态是否正确。 IN IN,OUT,INOUT是一个空的宏,只是用来说明这个参数是用于输入参数,还是输出的参数。 DriverEntry 操作系统在初始化驱动程序的时候会调用DriverEntry,通常会用这个函数来填充dispatch例程的指针,这就象注册回调函数一样。有的设备要创建设备的对象,或者还要创建一个设备名字,以及其他的初始化操作。它的原型: NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ){ } IN,OUT,INOUT是一个空的宏,只是用来说明这个参数是用于输入参数,还是输出的参数。NTSTATUS实际是个长整型可以在DDK头文件NTSTA TUS.H中找到NTSTATUS的代码列表。函数的第一个参数DriverObject是刚被初始化的驱动对象,就是操作系统为这个驱动分配的空间的指针。函数的第二个参数RegistryPath是驱动在注册表中的键值。如果驱动程序需要访问设备的服务键需要保存这个键值以备后用。 UNICODE_STRING UNICODE_STRING结构是通过使用各种本地安全认证(LSA)的功能来指定一个Unicode 字符串。 2结构体原型: typedef struct _LSA_UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer;} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING; 3结构成员: Length 指定字符串的长度,以字节为单位指出的Buffer字符串的长度。如果是以NULL字符结尾(即'\0'),则不包括NULL字符的长度。 MaximumLength Buffer字符串的总长度。 MaximumLength和Length的关系可以参照: char c[10] = "123"; sizeof(c);和strlen(c);得出的结果。

源程序程序破解之 API HOOK技术

【源程序】程序破解之API HOOK技术 API HOOK,就是截获API调用的技术,在程序对一个API调用之前先执行你的函数,然后根据你的需要可以执行缺省的API调用或者进行其他处理,假设如果想截获一个进程对网络的访问,一般是几个socket API : recv,recvfrom, send, sendto等等,当然你可以用网络抓包工具,这里只介绍通过API HOOK的方式来实现, 主要原理是在程序运行中动态修改目标函数地址的内存数据,使用jmp语句跳转到你的函数地址,执行完后再恢复内存数据, 汇编代码是: mov eax, pNewAddr[/size][size=3] jmp eax 读写进程内存方法: 1.读进程内存: 2.VirtualProtect(lpAddress, nSize, PAGE_READONLY, &dwOldProtect); 3.ReadProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwRead); 4.VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect); 2.写进程内存: VirtualProtect(lpAddress, nSize, PAGE_READWRITE, &dwOldProtect); WriteProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwWrite); VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect); 在很多年前这种技术非常的流行,有各种各样的工具和SDK,我自己也实现了一个C++ class,名为CAdHookApi, 主要几个函数是: class CAdHookApi { public: // 指定DLL的某个函数进行HOOK HANDLE Add(LPCTSTR lpszModule, LPCSTR lpcFuncName, void *pNewAddr, DWORD dwData = 0); // 给定一个函数地址进行HOOK HANDLE Add(void *pOldAddr, void *pNewAddr, const BYTE *verifyData = NULL, DWORD verifySize = 0, DWORD dwData = 0); BOOL Remove(HANDLE hHook); BOOL Begin(HANDLE hHook); BOOL End(HANDLE hHook); BOOL Begin2(void *pNewAddr); BOOL End2(void *pNewAddr); int BeginAll(); int EndAll(); };

相关文档
最新文档