Skip to content

Commit

Permalink
Support showing the system user infomations.
Browse files Browse the repository at this point in the history
  • Loading branch information
BeneficialCode committed Sep 18, 2024
1 parent 2256c82 commit ec09615
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 1 deletion.
12 changes: 12 additions & 0 deletions WinArk/MiscView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ LRESULT CMiscView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/,
L"Bypass Detect",
L"System Information",
L"Task Scheduler",
L"System Users"
};

int i = 0;
Expand All @@ -32,6 +33,7 @@ LRESULT CMiscView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/,
InitBypassDectectView();
InitSysInfoView();
InitTaskSchedView();
InitSystemUserInfoView();

return 0;
}
Expand Down Expand Up @@ -81,6 +83,10 @@ LRESULT CMiscView::OnTcnSelChange(int, LPNMHDR hdr, BOOL&) {
case TabColumn::TaskScheduler:
m_TaskSchedView.ShowWindow(SW_SHOW);
break;

case TabColumn::SysUserInfos:
m_pSysUserInfoView->ShowWindow(SW_SHOW);
break;
}
_index = index;
::PostMessage(m_hWnd, WM_SIZE, 0, 0);
Expand All @@ -98,6 +104,12 @@ void CMiscView::InitLogonSessionsView() {
m_hwndArray[static_cast<int>(TabColumn::LogonSessions)] = m_pLogonSessionView->m_hWnd;
}

void CMiscView::InitSystemUserInfoView() {
m_pSysUserInfoView = new CSystemUsersView(m_pFrame);
m_pSysUserInfoView->Create(m_hWnd, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0);
m_hwndArray[static_cast<int>(TabColumn::SysUserInfos)] = m_pSysUserInfoView->m_hWnd;
}

void CMiscView::InitSysInfoView() {
m_SysInfoView = new CSysInfoView(m_pFrame);
m_SysInfoView->Create(m_hWnd, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
Expand Down
6 changes: 5 additions & 1 deletion WinArk/MiscView.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "TaskSchedView.h"
#include "LogonSessionsView.h"
#include "BypassDlg.h"
#include "SystemUsersView.h"

class CMiscView :
public CWindowImpl<CMiscView> {
Expand All @@ -25,13 +26,14 @@ class CMiscView :
LRESULT OnTcnSelChange(int, LPNMHDR hdr, BOOL&);

enum class TabColumn :int {
LogonSessions, BypassDetect, SystemInformation, TaskScheduler
LogonSessions, BypassDetect, SystemInformation, TaskScheduler, SysUserInfos
};

void InitLogonSessionsView();
void InitBypassDectectView();
void InitSysInfoView();
void InitTaskSchedView();
void InitSystemUserInfoView();

private:
CContainedWindowT<CTabCtrl> m_TabCtrl;
Expand All @@ -47,4 +49,6 @@ class CMiscView :
CSysInfoView* m_SysInfoView{ nullptr };

CBypassDlg m_BypassView;

CSystemUsersView* m_pSysUserInfoView{ nullptr };
};
141 changes: 141 additions & 0 deletions WinArk/SystemUsersView.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include "stdafx.h"
#include "SystemUsersView.h"
#include <algorithm>
#include "SortHelper.h"
#include <Poco/DateTime.h>
#include <Poco/Timestamp.h>
#include <Poco/DateTimeFormatter.h>
#include <Poco/Timezone.h>
#include <lm.h>
#include <sddl.h>
#include <SecurityHelper.h>
#include "Helpers.h"


std::string CSystemUsersView::GetReadableTime(DWORD time) const {
Poco::Int64 timestamp = time;
if (timestamp == 0) {
return std::string("Never");
}

Poco::Timestamp ts(timestamp * Poco::Timestamp::resolution());
Poco::DateTime utcDateTime(ts);
int timeZoneOffset = Poco::Timezone::utcOffset();
Poco::DateTime localDateTime = utcDateTime + Poco::Timespan(timeZoneOffset, 0);
std::string readableTime = Poco::DateTimeFormatter::format(localDateTime, "%Y-%m-%d %H:%M:%S");
return readableTime;
}


CString CSystemUsersView::GetColumnText(HWND, int row, int col) const {
const auto& item = m_Users[row];

switch (col)
{
case 0:
return std::format(L"{:2d}", item.UserId).c_str();
case 1:
return item.UserName.c_str();
case 2:
return std::format(L"{:2d}", item.NumLogons).c_str();
case 3:
{
std::string time = GetReadableTime(item.LastLogon);
return Helpers::StringToWstring(time).c_str();
break;
}
case 4:
{
std::string time = GetReadableTime(item.LastLogoff);
return Helpers::StringToWstring(time).c_str();
break;
}
case 5:
{
return item.Sid.c_str();
}
default:
break;
}

return L"";
}

bool CSystemUsersView::IsUpdating() const {
return false;
}

void CSystemUsersView::DoSort(const SortInfo* si) {
return;
}

bool CSystemUsersView::IsSortable(HWND, int col) const {
return False;
}

LRESULT CSystemUsersView::OnCreate(UINT, WPARAM, LPARAM, BOOL&) {
m_hWndClient = m_List.Create(*this, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | LVS_SINGLESEL | LVS_REPORT | LVS_OWNERDATA | LVS_SHOWSELALWAYS);
m_List.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_LABELTIP);

auto cm = GetColumnManager(m_List);
cm->AddColumn(L"User Id", LVCFMT_RIGHT, 60, ColumnFlags::Mandatory | ColumnFlags::Const | ColumnFlags::Visible);
cm->AddColumn(L"User Name", LVCFMT_LEFT, 130, ColumnFlags::Mandatory | ColumnFlags::Const | ColumnFlags::Visible);
cm->AddColumn(L"Num Logons", LVCFMT_LEFT, 140, ColumnFlags::Mandatory | ColumnFlags::Const | ColumnFlags::Visible);
cm->AddColumn(L"Last Logon", LVCFMT_LEFT, 160, ColumnFlags::Mandatory | ColumnFlags::Const | ColumnFlags::Visible);
cm->AddColumn(L"Last Logoff", LVCFMT_LEFT, 160, ColumnFlags::Mandatory | ColumnFlags::Const | ColumnFlags::Visible);
cm->AddColumn(L"SID", LVCFMT_LEFT, 360, ColumnFlags::Mandatory | ColumnFlags::Const | ColumnFlags::Visible);

cm->UpdateColumns();

Refresh();

return 0;
}

void CSystemUsersView::Refresh() {
m_Users = EnumSystemUsers();
m_List.SetItemCountEx(static_cast<int>(m_Users.size()), LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL);
m_List.RedrawItems(m_List.GetTopIndex(), m_List.GetTopIndex() + m_List.GetCountPerPage());
}

std::vector<CSystemUsersView::UserInfo> CSystemUsersView::EnumSystemUsers() {
std::vector<UserInfo> infos;

NET_API_STATUS nStatus = NERR_Success;

do
{
LPUSER_INFO_3 pUserInfo = NULL;
DWORD entriesRead, totalEntries, resumeHandle = 0;
nStatus = NetUserEnum(NULL, 3, FILTER_NORMAL_ACCOUNT, (LPBYTE*)&pUserInfo,
MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resumeHandle);

if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA)) {
LPUSER_INFO_3 pTemp = pUserInfo;
infos.reserve(entriesRead);
for (int i = 0; i < entriesRead; i++) {
if (pTemp == NULL)
break;

UserInfo info;
info.UserName = pTemp->usri3_name;
info.Comment = pTemp->usri3_comment;
info.LastLogoff = pTemp->usri3_last_logoff;
info.LastLogon = pTemp->usri3_last_logon;
info.UserId = pTemp->usri3_user_id;
info.NumLogons = pTemp->usri3_num_logons;
info.Sid = SecurityHelper::GetSidFromUser(pTemp->usri3_name);

infos.emplace_back(std::move(info));
pTemp++;
}
}

if (pUserInfo != NULL) {
NetApiBufferFree(pUserInfo);
pUserInfo = NULL;
}
} while (nStatus == ERROR_MORE_DATA);

return infos;
}
43 changes: 43 additions & 0 deletions WinArk/SystemUsersView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once
#include "ViewBase.h"
#include "VirtualListView.h"
#include "resource.h"

class CSystemUsersView :
public CViewBase<CSystemUsersView>,
public CVirtualListView<CSystemUsersView> {
public:
CSystemUsersView(IMainFrame* frame):CViewBase(frame){}

BEGIN_MSG_MAP(CSystemUsersView)
MESSAGE_HANDLER(WM_CREATE,OnCreate)
CHAIN_MSG_MAP(CVirtualListView<CSystemUsersView>)
CHAIN_MSG_MAP(CViewBase<CSystemUsersView>)
END_MSG_MAP()

CString GetColumnText(HWND, int row, int col) const;
void DoSort(const SortInfo* si);
bool IsSortable(HWND, int col) const;
bool IsUpdating() const;

private:
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);

void Refresh();

std::string GetReadableTime(DWORD time) const;

private:
CListViewCtrl m_List;
struct UserInfo {
std::wstring UserName;
std::wstring Comment;
DWORD NumLogons;
DWORD LastLogon;
DWORD LastLogoff;
DWORD UserId;
std::wstring Sid;
};
std::vector<UserInfo> m_Users;
std::vector<UserInfo> EnumSystemUsers();
};
2 changes: 2 additions & 0 deletions WinArk/WinArk.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@
<ClCompile Include="SymbolFileInfo.cpp" />
<ClCompile Include="SysInfoView.cpp" />
<ClCompile Include="SystemConfigDlg.cpp" />
<ClCompile Include="SystemUsersView.cpp" />
<ClCompile Include="Table.cpp" />
<ClCompile Include="TaskHelper.cpp" />
<ClCompile Include="TaskSchedView.cpp" />
Expand Down Expand Up @@ -554,6 +555,7 @@
<ClInclude Include="SymbolFileInfo.h" />
<ClInclude Include="SysInfoView.h" />
<ClInclude Include="SystemConfigDlg.h" />
<ClInclude Include="SystemUsersView.h" />
<ClInclude Include="Table.h" />
<ClInclude Include="TaskHelper.h" />
<ClInclude Include="TaskSchedView.h" />
Expand Down
6 changes: 6 additions & 0 deletions WinArk/WinArk.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,9 @@
<ClCompile Include="KernelInlineHookDlg.cpp">
<Filter>Dialogs</Filter>
</ClCompile>
<ClCompile Include="SystemUsersView.cpp">
<Filter>Views</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
Expand Down Expand Up @@ -1025,6 +1028,9 @@
<ClInclude Include="KernelInlineHookDlg.h">
<Filter>Dialogs</Filter>
</ClInclude>
<ClInclude Include="SystemUsersView.h">
<Filter>Views</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WinArk.rc">
Expand Down

0 comments on commit ec09615

Please sign in to comment.