The opinions expressed in this blog are my own and do not represent those of my current employer

When it comes to working with memory of process, it comes handy to have information about whole address space of process, to do not touch PAGE_GUARD, knowing exec and writable pages, etc.

For that purpose i already implemented VadWalker in my kernel common repo, and also use it in DbiFuzz frmwrk. But recently i come accross some ideas, how to improve my recent approach and do it more efficiently and kinda smarter.

http://www.codemachine.com/figure_protopte_2.png

VadRoot is in fact simple AVL-tree, and AVL struct is commonly used accross windows kernel. For working in AVL-style in kernel come msdn with some support :

RtlInsertElementGenericTableAvl

RtlDeleteElementGenericTableAvl

RtlNumberGenericTableElementsAvl

RtlGetElementGenericTableAvl

RtlLookupFirstMatchingElementGenericTableAvl

…

For iterating this RTL_AVL_TABLE struct, i implement simple bstree methods, which i then used in AVL.hpp (LockedContainers.hpp), and same time i use this methods for walking trough VadRoot itself. But this approach leads to implement more and more logic, for iterating through VadRoot, so i start thinking about another method to not over-engineering myself too much..

At first some words about VadRoot AVL-tree struct. It seems that it is some kind of intrusive mechanism, which insert { parent, left, right } links into MMVAD_SHORT. Same time it have to be sanitized parent link, because is used method for storing additional info about node in last unused part of pointer [ sanitizatoin mask = ~sizeof(void*) ].
And it sounds familiar, do not ? boost::intrusive::avltree do same job already!

Problem can be that per different m$ versions it can be node-pointers stored at different offsets,

Now is *almost* solved problem with iterating trough VadRoot (getnext, getprev) and same time with classic functionality a.k.a. find, lower_bound…

Almost consist of two parts.

1. Still is problem, with creating header for avltree, as startpoint for iterating / finding algos

It can be solved, but not in clean way, in fact it is bit ohack. But on the other side, usage of VadRoot itself is ohack also … So key point is to create temporary boost::intrusive::avltree and insert inside dummy node, with NULL Vpn’s and redirect its pointer-links to VadRoot itself!
Here is bit of sample :

2. Next issue is with locking. For safe accessing VadRoot itself is necessary to locks AddressSapce & WorkingSet of process, mark thread which holding locks. And in addition, also MMVAD_SHORT nodes itselfs use locking mechanism for working with them, so go deeper

In my PoC i provide simple locked wrapper around VadRoot, and wraps functions { Contains, GetMemory, Find }. Which provide all necessary locking mechanism.
In addition Find resolve iterator represent targeted MMVAD_SHORT, and holds locks during work with this object.

C++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

classCVAdScanner:

publicboost::noncopyable

{

public:

...

static

__checkReturn

boolFind(

__in constCRange<void*>&mem,

__inout std::shared_ptr<CVadNode>*out

)

{

CDummyVad dummy_vad;

CVadNode*out_vadnode=nullptr;

{

CVADLock<CSharedLockWorker>lock;

if(!lock.IsLocked())

returnfalse;

if(!dummy_vad.RelinkToVadRoot())

returnfalse;

VadTree::iterator it=dummy_vad->find(mem,CMMVadShortCmp());

if(dummy_vad->end()==it)

returnfalse;

MMVAD_SHORT*c_mmvad=*it;

out_vadnode=newCVadNode(*it);

}

//outside of spinlock playing with std::shared_ptr

if(!out_vadnode)

returnfalse;

*out=std::shared_ptr<CVadNode>(out_vadnode);

returntrue;

}

...

}

classCVadNode:

publicboost::noncopyable,

privateCSharedLockWorker

{

public:

...

CVadNode*operator++()

{

//implement findNext, unlock current / lock new one, change m_vad to new one

}

...

}

So thats it, boost::intrusive seems can help in a lot of cases to simplify designs and needs for reinveinting wheels (like i already did in my previous approach), so lets boosting bit of kernel