找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 8882|回复: 8

端口读写的方法

 火.. [复制链接]

21

主题

110

回帖

4

精华

铂金会员

积分
7522
发表于 2012-1-17 00:30:45 | 显示全部楼层 |阅读模式
本帖最后由 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;
};

280

主题

203

回帖

0

精华

版主

积分
1808
发表于 2012-1-17 16:05:53 | 显示全部楼层
这年头 不管干点好事还是坏事 可能总会需要读写端口  特别是做外挂的时候 当WinIo被屏蔽掉之后  如果采用的还是老少皆宜的XP系统 那么 端口读写是有挺多种方法的 下面 给出几个范例方法 供参考  
感谢张帆  感谢tombkeeper 以及WinIo作者  好了 我分别给出方法 以及示例  忘了说了 这篇文章 发在黑防上 稍加改动 挪到这里了  看过黑防的直接无视好了

怎么连标点符号都没有?!

21

主题

110

回帖

4

精华

铂金会员

积分
7522
 楼主| 发表于 2012-1-17 16:46:37 | 显示全部楼层
额 帖子写的匆忙  没来得及  凑合着看吧 东西 都传在dbank上  稿子写得还是比较规范的  

0

主题

20

回帖

0

精华

初来乍到

积分
30
发表于 2012-1-17 17:20:19 | 显示全部楼层
瞧瞧  看看怎么回事

21

主题

110

回帖

4

精华

铂金会员

积分
7522
 楼主| 发表于 2012-2-9 17:48:31 | 显示全部楼层
R3下的3 4 6都是不适用的 XP以上

21

主题

110

回帖

4

精华

铂金会员

积分
7522
 楼主| 发表于 2012-2-9 17:51:16 | 显示全部楼层
需要注意的是直接写盘具体细节http://hi.baidu.com/mj0011/blog/ ... d8fa51242df20f.html
TA也在文章中有提及

0

主题

5

回帖

0

精华

初来乍到

积分
12
发表于 2012-5-21 19:31:05 | 显示全部楼层
Mark一下

2

主题

45

回帖

0

精华

铜牌会员

积分
214
发表于 2012-6-7 14:52:29 | 显示全部楼层
除了winio读写端口,其它都很模糊

7

主题

414

回帖

1

精华

铂金会员

积分
2173
发表于 2013-4-10 01:15:05 | 显示全部楼层
學習!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表