I'm developing a driver for monitoring process creation, I wrote a simple code to do it. I use the PsSetCreateProcessNotifyRoutineEx. But this doesn't work ! I exactly following Microsoft help on this link
#include <ntddk.h>
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
VOID UnloadRoutine(
IN PDRIVER_OBJECT DriverObject
);
VOID CreateProcessNotifyEx(
__inout PEPROCESS Process,
__in HANDLE ProcessId,
__in_opt PPS_CREATE_NOTIFY_INFO CreateInfo
);
VOID CreateProcessNotifyEx(
__inout PEPROCESS Process,
__in HANDLE ProcessId,
__in_opt PPS_CREATE_NOTIFY_INFO CreateInfo
)
{
if (CreateInfo)
{
if(CreateInfo->FileOpenNameAvailable==TRUE)
{
DbgPrintEx(
DPFLTR_IHVDRIVER_ID,
DPFLTR_INFO_LEVEL,
"PID : 0x%X (%d) ImageName :%wZ CmdLine : %wZ \n",
ProcessId,ProcessId,
CreateInfo->ImageFileName,
CreateInfo->CommandLine
);
}
}
}
VOID UnloadRoutine(IN PDRIVER_OBJECT DriverObject)
{
PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX) CreateProcessNotifyEx, TRUE);
DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,"Unloaded\n");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status = PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)CreateProcessNotifyEx, FALSE);
if(!NT_SUCCESS(status))
{
DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,"Faild to PsSetCreateProcessNotifyRoutineEx .status : 0x%X \n",status);
}
DriverObject->DriverUnload = UnloadRoutine;
DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,"Load\n");
return STATUS_SUCCESS;
}
This drive load and run correctly but when run a program(new process), Doesn't happen any thing and can't register PsSetCreateProcessNotifyRoutineEx and i got 0xC0000022 Error (Access Denied).
Any idea ?
Always i have to find my answer ;)
For passing this problem only need to add this value LINKER_FLAGS=/integritycheck to SOURCE file !
Before :
TARGETNAME=ProcView
TARGETPATH=.
TARGETTYPE=DRIVER
SOURCES=ProcView.c
Now :
TARGETNAME=ProcView
TARGETPATH=.
TARGETTYPE=DRIVER
LINKER_FLAGS=/integritycheck
SOURCES=ProcView.c
Related
I am a novice about boost::asio, I write a server, some clients can connect to it and keep listening.
class socket_server {
public:
~socket_server() { io_context.stop(); };
int server_process();
private:
boost::asio::io_context io_context;
};
int socket_server::server_process() {
try {
unlink("/var/run/socket");
server s(io_context, "/var/run/socket");
INFO("server_process, start run\n");
io_context.run();
} catch (std::exception &e) {
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
class server {
public:
server(boost::asio::io_context &io_context, const std::string &file)
: acceptor_(io_context, stream_protocol::endpoint(file)), socket_id_(0) {
do_accept();
}
private:
void do_accept();
stream_protocol::acceptor acceptor_;
int socket_id_;
};
void server::do_accept() {
INFO("do accept\n");
acceptor_.async_accept(
[this](std::error_code ec, stream_protocol::socket socket) {
if (!ec) {
INFO("new session create\n");
std::make_shared<session>(std::move(socket), socket_id_++)->start();
}
do_accept();
});
}
class session : public std::enable_shared_from_this<session> {
public:
session(stream_protocol::socket sock, int socket_id)
: socket_(std::move(sock)), socket_id_(socket_id) {}
~session() { socket_id_--; }
void start();
private:
void do_read();
void do_write(std::array<char, 1024> data);
int get_id() { return socket_id_; }
// The socket used to communicate with the client.
stream_protocol::socket socket_;
// Buffer used to store data received from the client.
std::array<char, 1024> data_;
int socket_id_;
};
void session::start() { do_read(); }
void session::do_read() {
INFO("in do_read\n");
auto self(shared_from_this());
socket_.async_read_some(
boost::asio::buffer(data_),
[this, self](std::error_code ec, std::size_t length) {
if (!ec) {
if (request.find("listen") != std::string::npos) {
std::unique_lock<std::mutex> lock(unsol_mutex);
unsol_cond.wait(lock)
do_write(get_unsol_data());
} else {
std::unique_lock<std::mutex> lock(send_mutex);
if (send_cond.wait_for(lock, std::chrono::seconds(2)) ==
std::cv_status::timeout) {
ERROR("response time out\n");
}
do_write(get_write_data());
}
}
});
}
In do_read(), I found when a client is listening (block in unsol_cond.wait(lock)), another client can not go to do_read().
Is it due to make_shared session? Is there a better implementation suggestion?
Thanks~
You're using blocking synchronization primitives in async code. That's an anti-pattern.
Firstly, as you noticed, the blocking operations will prevent the event loop from progressing.
Secondly, holding locks across async calls is often a bug (it doesn't guard the critical execution during execution of the async operation).
For simple integration with Asio proactor model, you can often
use a strand instead.
Under the hood, it will end up using mutexes, just like now, but only
if the concurrency model requires it. That mainly depends on the
execution context used and/or how many threads are running the
services.
Use a queue with a async send-chain. I have quite a few answers on this site that show you how to do that.
I would gladly demonstrate, but the code is too incomplete, and the naming doesn't really give me an idea what things mean ("listen"/"unsol"?, nothing ever signals those conditions so... hard to guess what they do in reality)
I use googletest as the main testing framework for a Qt project. QAbstractItemModelTester helps catching the most common errors in custom item model classes but I don't know how to integrate the reported failures(QTest) in a googletest unit test.
I didn't find any direct way to do this, but this is what I've done to have assertion for testing errors in QAbstractItemModelTester:
class AssertNoQtLogWarnings
{
static void messageHandlerTest(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
static bool NO_WARNING_MSG = true;
QByteArray localMsg = msg.toLocal8Bit();
const char* file = context.file ? context.file : "";
const char* function = context.function ? context.function : "";
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
break;
case QtWarningMsg:
EXPECT_EQ(false, NO_WARNING_MSG) << msg.toStdString();
break;
case QtCriticalMsg:
EXPECT_EQ(false, NO_WARNING_MSG) << msg.toStdString();
break;
case QtFatalMsg:
EXPECT_EQ(false, NO_WARNING_MSG) << msg.toStdString();
break;
}
}
public:
AssertNoQtLogWarnings()
{
qInstallMessageHandler(messageHandlerTest);
}
~AssertNoQtLogWarnings()
{
//Install default message handler
qInstallMessageHandler(nullptr);
}
};
TEST(QAbstractItemModel, QAbstractItemModel)
{
//RAII object. Any warning, critical or fatal message produced in this context
//will produce a GTest fail assertion
AssertNoQtLogWarnings logQtTest;
MyAbstractItemModel model;
QAbstractItemModelTester tester(&model, QAbstractItemModelTester::FailureReportingMode::Warning);
}
I need any advice how to continue CreateFile() hooking after getting code as follows:
#include<windows.h>
#include "C:\Detours\Detours-4.0.1\include\detours.h"
static HANDLE(WINAPI* TrueCreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile) = CreateFileW;
__declspec(dllexport) HANDLE WINAPI MyCreateFileW(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD
dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
if ((LPCTSTR)lpFileName == (LPCTSTR)L"C:\TestHook\file.txt")
{
return TrueCreateFileW((LPCTSTR)L"C:\TestHook\file.txt", dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
return TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
BOOL APIENTRY DLLMain(HMODULE hModule, DWORD reason_for_call, LPVOID lpReserved)
{
LONG error;
switch (reason_for_call)
{
case DLL_PROCESS_ATTACH:
OutputDebugString(L"Attaching HookingDLL.dll");
//OutputDebugString(strInfo);
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TrueCreateFileW, MyCreateFileW);
error = DetourTransactionCommit();
if (error == NO_ERROR)
{
OutputDebugString(L"Hooking attempt succeeded");
}
else
{
OutputDebugString(L"Hooking attempt failed");
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
OutputDebugString(L"Detaching HookingDLL.dll");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TrueCreateFileW, MyCreateFileW);
error = DetourTransactionCommit();
if (error == NO_ERROR)
{
OutputDebugString(L"Successfully detached hook");
}
else
{
OutputDebugString(L"Hook removal has failed");
}
break;
}
return TRUE;
}
What I need is a call of MyCreateFileW hooking when creating a new .txt file in Notepad++. Most likely, I have to add a DLL injector to aplly that hook, but in Internet I didn't find any comprehensible step-by-step guide for beginners (it's worth saying I'm a student). Could you suggest how to proceed with DLL injector in my case? Let me notice that I'm using Microsoft Detours to learn API hooking more smoothly and consistently.
You have already prepared the detour DLL. What you need do to is creating a new process and load DLLs into it with DetourCreateProcessWithDlls. Something like this:
DetourCreateProcessWithDll(NULL, "C:\\windows\\notepad.exe", NULL,
NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL,
&si, &pi, DetourPath, DLLPath, NULL);
You can refer to this tutorial "API Hooking with MS Detours" for more detailed information.
I have a large solution with 50+ unmanaged projects in it. I have recently added a project with managed code in it to the solution. The managed code accesses Windows.Devices.Sensors in a .NET dll. This dll is eventually wrapped by unmanaged code and called from another unmanaged project.
My problem is that I get the following access violation before main() even executes.
Unhandled exception at 0x744b8ea0 in myApplication.exe: 0xC0000005: Access violation.
Managed code:
#using <Windows.winmd>
using namespace Windows::Devices::Sensors;
#include <math.h>
namespace TabletSensors
{
namespace NET
{
public ref class DotNetDllClass
{
public:
DotNetDllClass()
{
Initialization();
}
~DotNetDllClass()
{
}
float* GetQuaternion()
{
OrientationSensorReading^ reading = _orientation->GetCurrentReading();
if( reading != nullptr )
{
float* quat = new float[4];
quat[0] = reading->Quaternion->X;
quat[1] = reading->Quaternion->Y;
quat[2] = reading->Quaternion->Z;
quat[3] = reading->Quaternion->W;
return quat;
}
else
{
return NULL;
}
}
private:
void Initialization()
{
_orientation = OrientationSensor::GetDefault();
if( _orientation != nullptr )
{
_orientation->ReportInterval = 16;
}
else
{
// not good ... throw exception or something
}
}
OrientationSensor^ _orientation;
};
}
}
Wrapper header file:
namespace TabletSensors
{
namespace NETWrapper
{
class DLLEXPORT_SENSORS WrapperClass
{
public:
__stdcall WrapperClass();
__stdcall ~WrapperClass();
float* __stdcall GetQuaternion();
};
}
}
Wrapper cpp file:
#define MIXSENSORS_BUILD
#include <gcroot.h>
#include "DotNetWrapper.h"
#include "DotNetDll.h"
using namespace TabletSensors::NETWrapper;
using namespace TabletSensors::NET;
static gcroot<TabletSensors::NET::DotNetDllClass^> Sensors = nullptr;
static System::UInt16 refCount = 0;
#pragma managed
inline TabletSensors::NET::DotNetDllClass^ GetSensors(void)
{
return (TabletSensors::NET::DotNetDllClass^)Sensors;
}
void Init()
{
++refCount;
if(GetSensors() == nullptr)
{
Sensors = gcnew TabletSensors::NET::DotNetDllClass();
}
}
void CleanUp()
{
if( refCount > 0 )
{
--refCount;
}
}
float* GetQuaternion_()
{
return Sensors->GetQuaternion();
}
#pragma unmanaged
TabletSensors::NETWrapper::WrapperClass::WrapperClass()
{
Init();
}
TabletSensors::NETWrapper::WrapperClass::~WrapperClass()
{
CleanUp();
}
float* TabletSensors::NETWrapper::WrapperClass::GetQuaternion()
{
float* x = new float[4];
return GetQuaternion_();
}
#pragma managed
Unmanaged project referencing my wrapper class:
#include "DotNetWrapper.h"
.
.
.
void UnmanagedProject::Update()
{
// if this line is present, I get an access violation without hitting any breakpoints.
TabletSensors::NETWrapper::WrapperClass _tabletSensors;
.
.
.
}
Since the managed code is trying to access Tablet Sensors I understand why it doesn't work on my Windows 7 desktop. What I don't understand it why it won't even allow me to debug my code at all. No breakpoints are hit before the Access Violation occurs.
What I would really like to figure out is how to use exception handling or #ifdefs to keep this crash from happening. But I have had very little luck.
Any ideas?
The fix is to Delay Load the managed DLL. The allows the application to run until that DLL is explicitly called. Thanks to Ben Voight for his answer here: https://stackoverflow.com/a/28467701/1454861
I'm trying to write a SSL-based async server using Boost ASIO example code from here.
I get the first message and its response correctly at the client side. Then, I send a second message which is received fine at the server, however when the response is sent to client. It comes as some gibberish.
I have uploaded the server code to pastebin. Also, find it below:
// file - Server.h
class Server
{
public:
explicit Server(const std::string &address,
int port,
std::size_t threadPoolSize);
// run the io_service loop
void run();
// stop the server
void stop();
private:
//handle async accept operation
void handleAccept(const boost::system::error_code &e);
// number of threads in thread pool
std::size_t _threadPoolSize;
// the io_service
boost::asio::io_service _ioService;
// acceptor to listen for incoming connections
boost::asio::ip::tcp::acceptor _acceptor;
std::string get_password()
{
return "password";
}
// ssl context
boost::asio::ssl::context _context;
ConnectionPtr _connection;
};
//////////////////////////////////////////////////////////////////////////
// file - Server.cpp
//////////////////////////////////////////////////////////////////////////
Server::Server(const std::string& address,
int port,
std::size_t threadPoolSize)
: _threadPoolSize(threadPoolSize),
_acceptor(_ioService),
_context(_ioService, boost::asio::ssl::context::sslv23),
_connection()
{
try {
DEBUG_2("Starting server on port: ", port);
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
_acceptor.open(endpoint.protocol());
_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
_acceptor.bind(endpoint);
_acceptor.listen();
_context.set_options(
boost::asio::ssl::context::default_workarounds
| boost::asio::ssl::context::no_sslv2
| boost::asio::ssl::context::single_dh_use);
_context.set_password_callback(boost::bind(&Server::get_password, this));
_context.use_certificate_chain_file("./demoCA/cacert.pem");
_context.use_private_key_file("./demoCA/private/cakey.pem",
boost::asio::ssl::context::pem);
// _context.use_tmp_dh_file("dh512.pem");
_connection.reset(new CclConnection(_ioService, _context));
_acceptor.async_accept(_connection->socket(),
boost::bind(&Server::handleAccept,
this,
boost::asio::placeholders::error));
}
catch(std::exception& e)
{
STD_EXCEPTION_MESSAGE;
throw;
}
}
void Server::run()
{
// Create a pool of threads to run all of the io_services.
std::vector<boost::shared_ptr<boost::thread> > threads;
for (std::size_t i = 0; i < _threadPoolSize; ++i)
{
boost::shared_ptr<boost::thread>
thread(new boost::thread(
boost::bind(&boost::asio::io_service::run,
&_ioService)
)
);
threads.push_back(thread);
}
// Wait for all threads in the pool to exit.
for (std::size_t i = 0; i < threads.size(); ++i)
threads[i]->join();
}
void Server::stop()
{
_ioService.stop();
}
void Server::handleAccept(const boost::system::error_code& e)
{
if (!e)
{
_connection->handshake();
_connection.reset(new CclConnection(_ioService, _context));
_acceptor.async_accept(_connection->socket(),
boost::bind(&Server::handleAccept,
this,
boost::asio::placeholders::error));
}
}
////////////////////////////////////////////////////////////
// file - Connection.h
////////////////////////////////////////////////////////////
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
typedef boost::asio::ssl::stream< boost::asio::ip::tcp::socket >
ssl_socket;
class Connection
: public boost::enable_shared_from_this<Connection>
{
public:
explicit Connection(boost::asio::io_service& io_service,
boost::asio::ssl::context& context);
//get socket from the connection
ssl_socket::lowest_layer_type& socket();
// do an SSL handshake
void handshake();
//get socket from the connection
boost::asio::io_service::strand& strand();
// start first async operation
void start();
void sendResponse(const Response& response);
void close();
// get remote IP address for this connection
std::string getIPAddress();
private:
void handleRead(const boost::system::error_code& e,
std::size_t bytesTransferred);
void handleWrite(const boost::system::error_code& e);
boost::asio::io_service::strand _strand;
ssl_socket _socket;
void handleHandshake(const boost::system::error_code& e);
boost::array<char, 8192> _buffer;
};
typedef boost::shared_ptr<Connection> ConnectionPtr;
///////////////////////////////////////////////////////////////
// File - Connection.cpp
///////////////////////////////////////////////////////////////
Connection::Connection(boost::asio::io_service& io_service,
boost::asio::ssl::context& context)
: _strand(io_service),
_socket(io_service, context)
{
}
ssl_socket::lowest_layer_type& Connection::socket()
{
return _socket.lowest_layer();
}
boost::asio::io_service::strand& Connection::strand()
{
return _strand;
}
void Connection::start()
{
_socket.async_read_some(boost::asio::buffer(_buffer),
_strand.wrap(
boost::bind(
&Connection::handleRead,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
)
);
}
void Connection::handshake()
{
std::cout << "doing ssl handshake" << std::endl;
_socket.async_handshake(boost::asio::ssl::stream_base::server,
_strand.wrap(
boost::bind(
&Connection::handleHandshake,
shared_from_this(),
boost::asio::placeholders::error
)
)
);
}
void Connection::handleHandshake(const boost::system::error_code& error)
{
if (!error)
{
_socket.async_read_some(boost::asio::buffer(_buffer),
_strand.wrap(
boost::bind(
&Connection::handleRead,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
)
);
}
else
{
std::cout << "error occured: " << error.message();
this->close();
}
}
void Connection::handleRead(const boost::system::error_code& e,
std::size_t bytesTransferred)
{
if (!e) {
// handle read data
this->start();
}
else {
this->close();
}
}
void Connection::handleWrite(const boost::system::error_code& e)
{
if (!e) {
this->start();
}
else {
this->close();
}
}
void Connection::sendResponse(const Response& response)
{
boost::asio::async_write(_socket,
boost::asio::buffer(convertToString(response)),
_strand.wrap(
boost::bind(
&Connection::handleWrite,
shared_from_this(),
boost::asio::placeholders::error
)
)
);
}
void Connection::close()
{
boost::system::error_code ignoredCode;
socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both,
ignoredCode);
}
std::string Connection::getIPAddress()
{
return socket().remote_endpoint().address().to_string();
}
Can someone point me out as to what is being done wrongly here?
Update: The issue is resolved as noted by me in the comment. The issue was exactly similar to another old question on stackoverflow.
Your code doesn't recognize, that boost::asio::buffer is only the wrapper for objects from which it was constructed.
Here (in Connection::sendResponse):
boost::asio::buffer(convertToString(response))
You created buffer out of a (probably) temporary object, which was destroyed before it was used by boost::asio::async_write.
Boost.Asio documentation specifically tells you about that in the paragraph "Buffer invalidation"
For the boost::asio::buffer overloads that accept an argument of type
std::string, the buffer objects returned are invalidated according to
the rules defined for invalidation of references, pointers and
iterators referring to elements of the sequence (C++ Std, 21.3).