A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #19092  by Stylo
 Sat Apr 27, 2013 8:25 am
Hi

I recently started to learn about ndis and tried using it's api, only when i compile my code i get unresolved external symbol __imp_<api name> where api name is the api i'm using
for example NdisRegisterProtocol..

that's my includes
Code: Select all
#include "ntddk.h"

#define NDIS40   1
#include "ndis.h"
#include "stdio.h"
the platform is windows xp 32bit
any ideas?
 #19095  by Vrtule
 Sat Apr 27, 2013 4:48 pm
Unresolved external symbols usually means you forgot to link certain static library to your project. This is done by the line you posted as the solution.
 #19194  by Stylo
 Sat May 04, 2013 4:54 pm
I came across to another problem trying to use Ndis.
I'm trying to write a network sniffer (as winpcap does)
i took the code sample from "Rootkits, subverting the windows kernel"
It compiled without any errors or anything, and set a callback whenever a packet is sniffed through my interface
but it never called
That's my source file..
Code: Select all
#include "ntddk.h"
// Important! Place this before ndis.h.
#define NDIS40   1
#pragma comment(lib,"ndis.lib") 
#include "ndis.h"
#include "stdio.h"


#define	ETHERNET_HEADER_LENGTH	14

typedef unsigned int UINT, *PUINT;

struct UserStruct {
	ULONG	mData;
} gUserStruct;

typedef struct _PACKET_RESERVED {
	LIST_ENTRY	ListElement;
	PIRP		Irp;
	PMDL		pMdl;
	BOOLEAN		FreeBufferAfterWrite;
	ULONG		Cpu;
} PACKET_RESERVED, *PPACKET_RESERVED;

NDIS_HANDLE		NdisAdapterHandle, NdisProtocolHandle;
NDIS_EVENT		CloseWaitEvent;

NDIS_HANDLE		PacketPoolHandle, BufferPoolHandle;

VOID OnSendDone(
  IN  NDIS_HANDLE ProtocolBindingContext,
  IN  PNDIS_PACKET Packet,
  IN  NDIS_STATUS Status
) {
	DbgPrint("OnSendDone Called\r\n");
}

VOID OnTransferDataDone(
  IN  NDIS_HANDLE ProtocolBindingContext,
  IN  PNDIS_PACKET Packet,
  IN  NDIS_STATUS Status,
  IN  UINT BytesTransferred
) {
	DbgPrint("OnTransferDataDone Called\r\n");
}

VOID OnResetDone(
  IN  NDIS_HANDLE ProtocolBindingContext,
  IN  NDIS_STATUS Status
) {
	DbgPrint("OnResetDone Called\r\n");
}

VOID OnRequestDone(
  IN  NDIS_HANDLE ProtocolBindingContext,
  IN  PNDIS_REQUEST NdisRequest,
  IN  NDIS_STATUS Status
) {
	DbgPrint("OnRequestDone Called\r\n");
}



VOID OnReceiveDoneStub(
  IN  NDIS_HANDLE ProtocolBindingContext
) {
	DbgPrint("OnReceiveDoneStub Called\r\n");
}

VOID OnStatus(
  IN  NDIS_HANDLE ProtocolBindingContext,
  IN  NDIS_STATUS GeneralStatus,
  IN  PVOID StatusBuffer,
  IN  UINT StatusBufferSize
) {
	DbgPrint("OnStatus Called\r\n");
}

VOID OnStatusDone(
  IN  NDIS_HANDLE ProtocolBindingContext
) {
	DbgPrint("OnStatusDone Called\r\n");
}

VOID OnBindAdapter(
  OUT  PNDIS_STATUS Status,
  IN   NDIS_HANDLE BindContext,
  IN   PNDIS_STRING DeviceName,
  IN   PVOID SystemSpecific1,
  IN   PVOID SystemSpecific2
) {
	DbgPrint("OnBindAdapter Called\r\n");
}

VOID OnUnbindAdapter(
  OUT  PNDIS_STATUS Status,
  IN   NDIS_HANDLE ProtocolBindingContext,
  IN   NDIS_HANDLE UnbindContext
) {
	DbgPrint("OnUnbindAdapter Called\r\n");
}

VOID OnProtocolUnload(VOID) {
	DbgPrint("OnProtocolUnload Called\r\n");
}

INT OnReceivePacket(
  IN  NDIS_HANDLE ProtocolBindingContext,
  IN  PNDIS_PACKET Packet
) {
	DbgPrint("OnReceivePacket Called\r\n");
	return 0;
}

NDIS_STATUS OnPNPEvent(
  IN  NDIS_HANDLE ProtocolBindingContext,
  IN  PNET_PNP_EVENT NetPnPEvent
) {
	DbgPrint("OnPNPEvent Called\r\n");
	return STATUS_SUCCESS;
}





VOID OnOpenAdapterDone(
  IN  NDIS_HANDLE ProtocolBindingContext,
  IN  NDIS_STATUS Status,
  IN  NDIS_STATUS OpenErrorStatus
) {
	NDIS_REQUEST	anNdisRequest;
	NDIS_STATUS		AnotherStatus;
	ULONG			Mode = NDIS_PACKET_TYPE_PROMISCUOUS;

	DbgPrint("OnOpenAdapterDone Called\r\n");

	if(NT_SUCCESS(OpenErrorStatus)) {
		anNdisRequest.RequestType										= NdisRequestSetInformation;
		anNdisRequest.DATA.SET_INFORMATION.Oid							= OID_GEN_CURRENT_PACKET_FILTER;
		anNdisRequest.DATA.SET_INFORMATION.InformationBuffer			= &Mode;
		anNdisRequest.DATA.SET_INFORMATION.InformationBufferLength		= sizeof(ULONG);

		NdisRequest(
			&AnotherStatus,
			NdisAdapterHandle,
			&anNdisRequest
		);

		NdisAllocatePacketPool(
			&Status,
			&PacketPoolHandle,
			256,
			sizeof(PACKET_RESERVED)
		);

		if(Status != NDIS_STATUS_SUCCESS) {
			DbgPrint("Allocate Packet Pool Failed\r\n");
			return;
		}

		NdisAllocateBufferPool(
			&Status,
			&BufferPoolHandle,
			256
		);

		if(Status != NDIS_STATUS_SUCCESS) {
			DbgPrint("Allocate Buffer Pool Failed\r\n");
			return;
		}
	}
	else {
		DbgPrint("OnOpenAdapterDone error: %08X\r\n", OpenErrorStatus);
	}
}




VOID OnCloseAdapterDone(
  IN  NDIS_HANDLE ProtocolBindingContext,
  IN  NDIS_STATUS Status
) {
	NdisSetEvent(&CloseWaitEvent);

	DbgPrint("OnCloseAdapterDone Called\r\n");
}


NDIS_STATUS OnReceiveStub(
  IN  NDIS_HANDLE ProtocolBindingContext,
  IN  NDIS_HANDLE MacReceiveContext,
  IN  PVOID HeaderBuffer,
  IN  UINT HeaderBufferSize,
  IN  PVOID LookAheadBuffer,
  IN  UINT LookaheadBufferSize,
  IN  UINT PacketSize
) {
	PNDIS_PACKET		pPacket;
	PNDIS_BUFFER		pBuffer;
	ULONG				SizeToTransfer = 0;
	NDIS_STATUS			Status;
	UINT				BytesTransfered;
	ULONG				BufferLength;
	PPACKET_RESERVED	Reserved;
	NDIS_HANDLE			BufferPool;
	PVOID				Temp;
	UINT				FrameType;

	DbgPrint("OnReceiveStub Called\r\n");

	SizeToTransfer	= PacketSize;
	FrameType		= 0;

	if(HeaderBufferSize > ETHERNET_HEADER_LENGTH || SizeToTransfer > (1514 - ETHERNET_HEADER_LENGTH)) {
		DbgPrint("OnReceiveStub returning unaccepted packet\r\n");
		return NDIS_STATUS_NOT_ACCEPTED;
	}

	memcpy(
		&FrameType,
		(((char*)HeaderBuffer) + 12),
		2
	);

	if(FrameType != 0x0008) {
		DbgPrint("Ignoring non ethernet frames\r\n");
		return NDIS_STATUS_NOT_ACCEPTED;
	}

	Temp = ExAllocatePool(NonPagedPool, (1514 - ETHERNET_HEADER_LENGTH));

	if(Temp) {
		RtlZeroMemory(Temp, (1514 - ETHERNET_HEADER_LENGTH));
		NdisAllocatePacket(
			&Status,
			&pPacket,
			PacketPoolHandle,
		);

		if(NDIS_STATUS_SUCCESS == Status) {
			DbgPrint("Store ethernet header\r\n");

			RESERVED(pPacket)->pHeaderBufferP = ExAllocatePool(NonPagedPool, ETHERNET_HEADER_LENGTH);
		}
	}

	return NDIS_STATUS_SUCCESS;
}



VOID SendRaw(char *c, int len) {
	NDIS_STATUS		Status;
	
	DbgPrint("SendRaw Called\r\n");


}



VOID DriverUnload(PDRIVER_OBJECT pDriverObject) {
	NDIS_STATUS		Status;

	DbgPrint("DriverUnload Called\r\n");

	NdisResetEvent(&CloseWaitEvent);
	NdisCloseAdapter(&Status, NdisAdapterHandle);

	if(Status == NDIS_STATUS_PENDING) {
		DbgPrint("Pending wait event\r\n");
		NdisWaitEvent(&CloseWaitEvent, 0);
	}

	NdisDeregisterProtocol(&Status, NdisProtocolHandle);
	if(FALSE == NT_SUCCESS(Status)) {
		DbgPrint("Deregister failed\r\n");
	}
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) {
	UINT							MediumIndex	= 0;
	NDIS_STATUS						Status, ErrorOpenStatus;
	NDIS_MEDIUM						MediumArray = NdisMedium802_3;
	UNICODE_STRING					usAdapterName;
	NDIS_PROTOCOL_CHARACTERISTICS	ProtocolCharacteristics;
	NDIS_STRING						ProtoName	= NDIS_STRING_CONST("Stage3");

	DbgPrint("Loading . .\r\n");

	RtlInitUnicodeString(
		&usAdapterName,
		L"<myInterface>"
	);

	NdisInitializeEvent(&CloseWaitEvent);
	pDriverObject->DriverUnload = DriverUnload;

	RtlZeroMemory(&ProtocolCharacteristics, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

	ProtocolCharacteristics.MajorNdisVersion			= 4;
	ProtocolCharacteristics.MinorNdisVersion			= 0;
	ProtocolCharacteristics.Reserved					= 0;
	ProtocolCharacteristics.OpenAdapterCompleteHandler  = OnOpenAdapterDone;
	ProtocolCharacteristics.CloseAdapterCompleteHandler = OnCloseAdapterDone;
	ProtocolCharacteristics.SendCompleteHandler         = OnSendDone;
	ProtocolCharacteristics.TransferDataCompleteHandler = OnTransferDataDone;
	ProtocolCharacteristics.ResetCompleteHandler        = OnResetDone;
	ProtocolCharacteristics.RequestCompleteHandler      = OnRequestDone;
	ProtocolCharacteristics.ReceiveHandler              = OnReceiveStub;
	ProtocolCharacteristics.ReceiveCompleteHandler      = OnReceiveDoneStub;
	ProtocolCharacteristics.StatusHandler               = OnStatus;
	ProtocolCharacteristics.StatusCompleteHandler       = OnStatusDone;
	ProtocolCharacteristics.Name                        = ProtoName;
	ProtocolCharacteristics.BindAdapterHandler          = OnBindAdapter;
	ProtocolCharacteristics.UnbindAdapterHandler        = OnUnbindAdapter;
	ProtocolCharacteristics.UnloadHandler               = OnProtocolUnload;
	ProtocolCharacteristics.ReceivePacketHandler        = OnReceivePacket;
	ProtocolCharacteristics.PnPEventHandler             = OnPNPEvent;

	DbgPrint("Registering NDIS Protocol\r\n");

	NdisRegisterProtocol(
		&Status,
		&NdisProtocolHandle,
		&ProtocolCharacteristics,
		sizeof(NDIS_PROTOCOL_CHARACTERISTICS)
	);

	if(Status != NDIS_STATUS_SUCCESS) {
		DbgPrint("NdisRegisterProtocol failed, error: %08X\r\n", Status);
		return Status;
	}

	NdisOpenAdapter(
		&Status,
		&ErrorOpenStatus,
		&NdisAdapterHandle,
		&MediumIndex,
		&MediumArray,
		1,
		NdisProtocolHandle,
		&gUserStruct,
		&usAdapterName,
		0,
		NULL
	);

	if(Status != NDIS_STATUS_PENDING) {
		if(NT_SUCCESS(Status) == FALSE) {
			DbgPrint("No Success, error: %08X\r\n", Status);
			if(Status == NDIS_STATUS_ADAPTER_NOT_FOUND) {
				DbgPrint("No adapter found\r\n");
			}

			NdisDeregisterProtocol(&Status, NdisProtocolHandle);
			if(NT_SUCCESS(Status) == FALSE) {
				DbgPrint("NdisDeregisterProtocol Failed\r\n");
			}

			return STATUS_UNSUCCESSFUL;
		}
		else {
			DbgPrint("Calling OnOpenAdapterDone\r\n");
			OnOpenAdapterDone(
				&gUserStruct,
				Status,
				NDIS_STATUS_SUCCESS
			);
		}
	}

	return STATUS_SUCCESS;
}
Thanks