64位核心開發第十七講,WSK下的Berkeley API操作
64位核心開發第十七講,WSK下的Berkeley API操作
一丶 Wsk Berkeley socket 簡介
1.1 簡介
在瞭解了WSK
之後 我們按理說應該繼續往下寫.必須寫一下原理.但是我感覺這東西就跟汽車一樣.你總要先學會開車
然後才能學修車
. 這樣在瞭解車的前提下學習修車的時候才能更好的理解汽車為什麼這樣設計. 當然不排除 直接學習 修車. 但是這樣付出的時間也會更多.所謂知己知彼百戰百勝.
如果我們要寫WSK網路通訊肯定要寫很底層的程式碼,包括不限於(IRP操作 WSK的排程表操作. WSK的註冊 反註冊操作). 這些我們需要在第三講才能接觸到. 而現在 核心下面已經有人幫我們把 WSK的操作封裝為了Berkeley API的操作
如我們我們學習 Berkeley
API操作那麼就會簡單了. 直接 socket
操作即可.
PS: 在學習之前 請一定熟悉 windows下的 socket程式設計. 只有懂了 ring3層面的網路程式設計 才會明白 Berkeley 怎麼程式設計.(或者你是學習linux的 也熟悉socket程式設計)
1.2 Berkeley 下的 TCP Client模型
根據大神提供的 Berkeley 介面.我們可以直接使用介面來讀取或者傳送資料.
在使用 Berkeley socket之前一定要記得初始化與反初始化
.(結束的時候反初始化即可)
介面如下:
KsInitialize()
KsDestroy()
在進行資料的傳送之前我們需要知道 TCP的Client模型是什麼.以及其對應的步驟.
步驟如下:
1.建立流式socket
2.將套接字與遠端主機進行連結
3.在套接字上讀/寫資料
4.關閉socket結束會話.
根據流程我們在RING3下的程式碼為如下:
#include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WSADATA data; if (WSAStartup(MAKEWORD(2, 2), &data)) { puts("對不起初始化失敗\r\n"); system("pause"); } //1.建立 SOCKET hClient; hClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == hClient) { printf("socket 失敗\r\n"); goto OPT; } //2.連線 sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //指定IP跟端口才能連線 addr.sin_port = htons(8564); connect(hClient, (sockaddr *)&addr, sizeof(addr));//指明服務端資訊.才能進行通訊. //3.收發資料. char pszBuffer[100] = "HelloWorld"; send(hClient, pszBuffer, sizeof(char) * 100,0); OPT: closesocket(hClient); //釋放一切資源. WSACleanup(); getchar(); return 0; }
而在核心層面我們一樣也是上面的步驟.只不過API使用的不同.
原因是在作者在封裝WSK的時候很多WSK並不能直接封裝為一個函式.所以作者又在後面加了很多名字,以此來告訴我們需要需要填寫增加的資訊是什麼.
在核心層 TCP的傳送模型為如下:
1.根據域名尋找目標主機IP getaddrinfo() /getsockaddrbyhost()
2.socket_connection() 建立流式套接字(對應ring3 socket()函式 )
3.connect() 連結 目標主機
4.send() 傳送TCP資料
5.closesocket() 關閉連結
.....
反初始化
程式碼如下:
我是將 wsk Berkeley 的API操作封裝成C++的形式了.所以程式碼展示是類函式
NTSTATUS CNtddkSocket::SendTcpData(char *domain_name, char *port, char *send_value, int send_value_size)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
SOCKADDR_IN server_addr = {0};
int sockfd = -1;
int result = -1;
do
{
if (m_isInitSocket == FALSE)
{
#ifdef DBG_SOCKET_PRINT
KdPrint(("SendTcpData Error No InitSock()\r\n"));
#endif DBG_SOCKET_PRINT
status = STATUS_UNSUCCESSFUL;
return status;
}
result = getsockaddrbyhost(domain_name, port, &server_addr);
if (!NT_SUCCESS(result))
{
#ifdef DBG_SOCKET_PRINT
KdPrint(("SendTcpData Error getsockaddrbyhost()\r\n"));
#endif DBG_SOCKET_PRINT
status = STATUS_UNSUCCESSFUL;
return status;
}
sockfd = socket_connection(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd == -1)
{
#ifdef DBG_SOCKET_PRINT
KdPrint(("SendTcpData Error socket_connection()\r\n"));
#endif DBG_SOCKET_PRINT
status = STATUS_UNSUCCESSFUL;
return status;
}
result = connect(sockfd, (SOCKADDR *)&server_addr, sizeof(server_addr));
if (result == -1)
{
#ifdef DBG_SOCKET_PRINT
KdPrint(("SendTcpData Error connect()\r\n"));
#endif DBG_SOCKET_PRINT
status = STATUS_UNSUCCESSFUL;
break;
}
result = send(sockfd, send_value, send_value_size, 0);
if (result == -1)
{
#ifdef DBG_SOCKET_PRINT
KdPrint(("SendTcpData Error send()\r\n"));
#endif DBG_SOCKET_PRINT
status = STATUS_UNSUCCESSFUL;
break;
}
#ifdef DBG_SOCKET_PRINT
else
{
KdPrint(("SendTcpData Data len = %d\r\n", result));
}
#endif DBG_SOCKET_PRINT
closesocket(sockfd);
} while (FALSE);
return status;
}
呼叫示例 虛擬碼:
g_ntddksocket.InitSocket();
g_ntsocket->SendTcpData(
"www.baidu.com",
"80",
"wsk->send: HelloWorld",
strlen("wsk->send: HelloWorld"));
NtddkThread.ThSleep(1000 * 5);
g_ntddksocket.UnInitSocket();
抓包結果如下:
作者:IBinary 出處:https://www.cnblogs.com/iBinary/堅持兩字,簡單,輕便,但是真正的執行起來確實需要很長很長時間.當你把堅持兩字當做你要走的路,那麼你總會成功. 想學習,有問題請加群.群號:725864912(收費)群名稱: 逆向學習小分隊 群裡有大量學習資源. 以及定期直播答疑.有一個良好的學習氛圍. 涉及到外掛反外掛病毒 司法取證加解密 驅動過保護 VT 等技術,期待你的進入。
詳情請點選連結檢視置頂部落格 https://www.cnblogs.com/iBinary/p/7572603.html