|
本帖最后由 KMSRussian 于 2012-1-18 00:04 编辑
这年头,不管干点好事还是坏事,可能总会需要读写端口。特别是做外挂的时候,当WinIo被屏蔽掉之后 ,如果采用的还是老少皆宜的XP系统,那么,端口读写是有挺多种方法的,平常收藏几个也是不错的选择,下面,给出几个范例方法供参考。
感谢张帆,感谢tombkeeper 以及WinIo作者。 好了,我分别给出方法,以及示例。忘了说了, 这篇文章发在黑防上稍加改动挪到这里了,看过黑防的飘过就好了。
1 六个宏定义
READ_PORT_UCHAR READ_PORT_USHORT READ_PORT_ULONG
WRITE_PORT_UCHAR WRITE_PORT_USHORT WRITE_PORT_ULONG
需要驱动
2内嵌汇编IN OUT的使用
需要驱动
3NativeAPINtSystemDebugControl
无需驱动
4修改IOPM标志
无需驱动当然有驱动更稳定
5WinIO的使用
需要驱动
6ZwSetInformationProcess_Address
无需驱动
方法挺多的,把代码都贴出来,太冗余。我捡主要的说。
对了,所有的东东,从这个地址下载 http://dl.dbank.com/c0o8oqniw1。
1 第一种方法 我在代码中注释的比较详细,原始出处,出自张帆老大的windows驱动开发技术详解,不过,他写的那个代码,明显有很多赘余的成分,所以我删节了,称之为精简版本。 原理挺简单的是微软推荐的标准做法吧 。
2 第二种方法和第一种方法是一样的,只是第一种方法的汇编版本,注释也是很详细 不需要多加解释。
3 第三种方法和第六种方法,Native API啦,在XP底下还是很好用的。
给出NtSystemDebugControl的代码,复制黏贴VC6 CUI编译就好了。注释的也还行
有疑问的话可以搜索这两个资料:一个是NativeAPI、另一个就是tombkeeper老大的《对Native API NtSystemDebugControl的分析》或者自己windbg跟一下。
实际上就是这样的
NtSystemDebugControl--->KdpSysReadIoSpace--->三个宏定义
NtSystemDebugControl--->KdpSysWriteIoSpace--->三个宏定义
//演示用ZwSystemDebugControl读写端口清除CMOS密码
//详细信息 请见 对Native API NtSystemDebugControl的分析 这篇文章
//代码直接在XP SP3下拖进CMD窗口运行即可 我在XP SP3下的虚拟机里测试成功
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "advapi32")
#define NTAPI __stdcall
#define FCHK(a) if (!(a)) {printf(#a " failed\n"); return 0;} //定义了一个宏 宏中的a不成立的话 输出a失败 类似于assert断言
typedef int NTSTATUS;
typedef enum _SYSDBG_COMMAND
{
SysDbgSysReadIoSpace = 14,
SysDbgSysWriteIoSpace = 15
}SYSDBG_COMMAND, *PSYSDBG_COMMAND;
typedef NTSTATUS (NTAPI * PZwSystemDebugControl) (
SYSDBG_COMMAND ControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength,
PULONG ReturnLength
);
PZwSystemDebugControl ZwSystemDebugControl = NULL;
typedef struct _IO_STRUCT
{
DWORD IoAddr; // IN: Aligned to NumBYTEs,I/O address
DWORD Reserved1; // Never accessed by the kernel
PVOID pBuffer; // IN (write) or OUT (read): Ptr to buffer
DWORD NumBYTEs; // IN: # BYTEs to read/write. Only use 1, 2, or 4.
DWORD Reserved4; // Must be 1
DWORD Reserved5; // Must be 0
DWORD Reserved6; // Must be 1
DWORD Reserved7; // Never accessed by the kernel
}
IO_STRUCT, *PIO_STRUCT;
//紧接着下面封装了一个提升进程权限的代码 不知道的兄弟可参考这里 http://hi.baidu.com/invisiable/b ... a4a68f461064fb.html
//windows核心编程里面也有
BOOL EnablePrivilege (PCSTR name)
{
HANDLE hToken;
BOOL rv;
TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} };
/*
typedef struct _TOKEN_PRIVILEGES { DWORD PrivilegeCount; LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
typedef struct _LUID_AND_ATTRIBUTES { LUID Luid; DWORD Attributes;
} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES;
typedef struct _LUID { DWORD LowPart; LONG HighPart;
} LUID, *PLUID;
我们要怎么样才能知道一个权限对应的LUID值是多少呢?这就要用到另外一个API函数LookupPrivilegevalue
*/
LookupPrivilegeValue (
0,
name,
&priv.Privileges[0].Luid
);
OpenProcessToken(
GetCurrentProcess (),
TOKEN_ADJUST_PRIVILEGES,
&hToken
);
AdjustTokenPrivileges (
hToken,
FALSE,
&priv,
sizeof priv,
0,
0
);
rv = GetLastError () == ERROR_SUCCESS;
CloseHandle (hToken);
return rv;
}
BYTE InPortB (int Port)
{
BYTE Value;
IO_STRUCT io;
io.IoAddr = Port;
io.Reserved1 = 0;
io.pBuffer = (PVOID) (PULONG) & Value;
io.NumBYTEs = sizeof (BYTE);
io.Reserved4 = 1;
io.Reserved5 = 0;
io.Reserved6 = 1;
io.Reserved7 = 0;
ZwSystemDebugControl
(
SysDbgSysReadIoSpace,
&io,
sizeof (io),
NULL,
0,
NULL
);
return Value;
}
void OutPortB (int Port, BYTE Value)
{
IO_STRUCT io;
io.IoAddr = Port;
io.Reserved1 = 0;
io.pBuffer = (PVOID) (PULONG) & Value;
io.NumBYTEs = sizeof (BYTE);
io.Reserved4 = 1;
io.Reserved5 = 0;
io.Reserved6 = 1;
io.Reserved7 = 0;
ZwSystemDebugControl
(
SysDbgSysWriteIoSpace,
&io,
sizeof (io),
NULL,
0,
NULL
);
};
int main (void)
{
HMODULE hNtdll;
// ULONG ReturnLength;
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
EnablePrivilege (SE_DEBUG_NAME);
FCHK ((hNtdll = LoadLibrary ("ntdll.dll")) != NULL);
FCHK ((ZwSystemDebugControl = (PZwSystemDebugControl)
GetProcAddress (hNtdll, "ZwSystemDebugControl")) != NULL);
FCHK ((void *) GetVersionEx (&OSVersionInfo) != NULL);
if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
OSVersionInfo.dwMajorVersion >= 5 &&
OSVersionInfo.dwMinorVersion >= 1) //Windows XP以上
{
OutPortB(0X70,(BYTE)(12345678));
OutPortB(0X71,(BYTE)(87654567));
printf("success");
}
else
{
printf ("This program require Windows XP or Windows 2003.\n");
}
return 0;
}
接着说说第六种方法。传送门 http://www.vbasm.com/thread-6187-1-1.html
下载附件,其中的SRC,直接I/O就是用NtSetInformationProcess读写端口的。 准确的说是ZwSetProcessInformation读写端口的。
效果就是破坏掉了还原卡。但是当您看到我给出的这些事例的时候,您如果通过端口读写破坏还原的话,想必方法就大大增多了吧。 呵呵。
4 依然是传送门。由于这个方法看雪的combojiang大侠有详细的介绍,再这里不再浪费篇幅详细介绍了大家可以参考这个帖子,介绍的很详细。
http://bbs.pediy.com/showthread.php?p=434124#post434124
5 WinIo调用的也是六个宏定义,这里为什么拿出篇幅来说这个呢,因为WinIo对于各个版本的windows都支持的很好。WIN2000-WIN7版本都支持,当然X64上WinIo没有签名,调用的方法帮助文档里面也说的很清楚,我给出两个示例来说明WinIo的使用。
方法1使用.lib文件的时候加载DLL代码如下。此方法需要用VS2008编译下winio得到lib文件
#include "stdio.h"
#include "windows.h"
#include ".\WinIo\Source\Dll\winio.h"
#pragma comment(lib,"WinIo32")//tell the compiler where the file is w
WCHAR *str=L".\\WinIo\\Binaries\\WinIo32.sys";
int main()
{
// HMODULE hlib = LoadLibrary("WinIo32.dll");
//PVOID p = GetProcAddress(hlib , "InitializeWinIo");
bool _stdcall a= InitializeWinIo();
if (a==0)
{
printf("WinIo初始化失败");
}
else
{
bool bReta=SetPortVal(0x70,12224344,4);
bool bRetb=SetPortVal(0x71,34543534,4);
if(bReta&&bRetb)
printf("successful");
//关闭WinIO驱动
ShutdownWinIo();
}
return 0;
};
方法2 不使用.lib文件 使用LoadLibrary 和GetProcAddress动态加载
我第一次编译WinIo获取lib文件的时候失败了,后来把VS2008重新修复了一遍编译成功,鉴于这种情况我给一个动态加载的方法。
#include "stdio.h"
#include "windows.h"
#include ".\WinIo\Source\Dll\winio.h"
//#pragma comment(lib,"WinIo32")//tell the compiler where the file is w
//WCHAR *str=L".\\WinIo\\Binaries\\WinIo32.sys";
//bool SetPortVal(WORD wPortAddr,DWORD dwPortVal,BYTE bSize);
//void ShutdownWinIo();
typedef bool (_stdcall *bRet1)();
typedef bool (_stdcall *bRet2)(WORD wPortAddr,DWORD dwPortVal,BYTE bSize);
typedef void (_stdcall *bVoid)();
int main()
{
HMODULE h1=::LoadLibrary("WinIo32.dll");
if (h1 !=NULL)
{
//bool _stdcall InitializeWinIo();
//2 地址 代理函数=(地址)::GetProcAddress(h,"原函数")
bRet1 iz=(bRet1)::GetProcAddress(h1,"InitializeWinIo");
if(!iz)
{
printf("fale in InitializeWinIo GetProcAddress");
}
else
{
bRet2 SPV=(bRet2)::GetProcAddress(h1,"SetPortVal");
if (!SPV)
{printf("fale in SetPortVal GetProcAddress");}
else
{
bVoid SD=(bVoid)::GetProcAddress(h1,"ShutdownWinIo");
if (!SD)
{printf("fale in ShutdownWinIo GetProcAddress");}
else
{
bool a= iz();
if (a==0)
{
printf("WinIo初始化失败");
}
else
{
bool bReta=SPV(0x70,12224344,4);
bool bRetb=SPV(0x71,34543534,4);
if(bReta&&bRetb)
printf("successful");
//关闭WinIO驱动
SD();
::FreeLibrary(h1);
}
}
}
}
}
return 0;
}; |
|