Title: Detecting Memory Access Errors via Illegal Write Monitoring
1Detecting Memory Access ErrorsviaIllegal Write
Monitoring
- Ongoing Research
- by
- Emre Can Sezer
2ASLANLAR '05
3Outline
- Quick wrap-up of last semesters presentation
- Basic design
- Problems and Solutions
- Pointers
- Structure types
- Discussion
- Performance considerations
- Applications
4Wrap-up of last semesters talk
- C is not type safe, and continue to have
vulnerabilities - Worm outbreaks
- NIDSs can only detect random scanning worms
- NIDSs accept a certain number of casualties
- Data attacks evade most HIDSs
- We need a good host-based framework to detect a
broad range of memory corruption attacks
5Main Observation with an Illustrative Example
- Line 11 can overflow buffer.
- Line 11 should only be writing to buffer.
Activation Record of func() on stack
1 void func () 2 int isAdmin 3
char buffer255 4 isAdmin 0 5 if
( check_pssw(buffer) ) 6 isAdmin 1 7
else 8 isAdmin 0 9 10
11 scanf (s, buffer) 12 13
if (isAdmin) else 14 15
return 16
Ret. address
isAdmin
Buffer255
6Basic Design
- Observation A memory location is only modified
by a small number of instructions. - Idea
- Select a list of memory locations to monitor
- For every location determine the list of
instructions that can modify it, called the
memory locations write set (WS). - At runtime perform checks to ensure monitored
memory locations are only modified by
instructions in their WS. - Implementation has two parts
- Static analysis
- Dynamic monitoring
7Static Analysis
- Use source code analysis
- For every variable, determine the variables WS.
- Assignment instructions where the variable is on
the LHS. - Library function calls in which the variable is
used as an argument that the function can modify
(i.e. memcpy()) - Current implementation uses Code Surfer
- A script automatically extracts all the
information required
8Dynamic Monitoring
- Terminology
- Monitoring agent is called agent for short
- The list of memory locations that are being
monitored is M. - Illegal write checking
- Capturing of memory writes and set membership
checks - State maintenance
- Capturing function calls and returns
- Capturing malloc family of function calls
- Points to tracking for pointers
- We have written a skin for Valgrind, an open
source x86 emulator, for dynamic monitoring
9System Overview
10Problems and Solutions
- Static Analysis and Dynamic Monitoring dont
talk the same language
Static Analysis Dynamic Monitoring
Variable names Memory addresses
Line numbers Program counter (PC)
If code is compiled with debug flags, a PC can be
translated into a file name and line number.
11Finding variables on memory
- Global variables
- Reside in the data segment
- Have fixed addresses
- Local variables
- Their addresses depend on the function call stack
- They are defined as offsets from the beginning of
the functions activation record - Function calls must be monitored at runtime
12Problem Good old pointers
1 void main () 2 int array 3 array
(int ) malloc (10sizeof(int)) 4 array5
42 5
- Line 4 is writing to a heap location
- How do we monitor and associate with line 4?
- Solution
- For a pointer p, keep two separate WSs
- One for the pointer variable itself WS(p)
- Another for the memory region it points to
WS(ref(p)) - At runtime determine ref(p) and add WS(ref(p)) to
ref(p)s WS.
13Problem Good old pointers
- Side benefits
- Inter-procedural static analysis is not required.
- Pointer aliasing and arithmetic can be handled.
14Problem Good old pointers
- 1 int square (int num)
- 2 num (num) (num)
- 3
- 4 void main ()
- 5 int a
- 6 scanf (d, a)
- 7 square (a)
- 8 printf (d\n, a)
- 9
- If a function has pointer type formal arguments,
we check where they point to at function call
time - In this example, line 2 is added to as WS.
15Problem Chained Dereferences
1 int z 2 int y z 3 int x y 4
x 5
1 int z 2 int y z 3 int x y 4a
int temp1 x 4b temp1 5
- Our current approach cannot handle this situation
- Relation between line 4 and var z is lost
- Solution
- Use source code rewriting
- Replace all complex dereferences with simple
dereferences by introducing temporary variables
16Problem Structures
struct int num
char str4 entry 1 int
main () 2 struct entry var 3
strcpy(var.str, "Hello") 4 return 0 5
- struct
- int num
- char str4
- entry
- int main()
- 2 struct entry base
- 3 struct entry var base
- 4 strcpy(var-gtstr, "Hello")
- 5
- Not handled in our current implementation
- Solution
- Treat every field of a structure as a separate
variable with its own WS - Instructions operating on a structure variable is
added to each fields WS seperately
17Discussion Capabilities
- Detects memory corruption errors at the time of
write - Can provide information about
- Instruction causing the error
- Variable that was illegitimately written to
- Current user stack
- The error type (buffer overflow, double free etc.)
18Discussion Performance
- No real performance results yet
- Expecting to see 20x slow down
- We keep data structures for each variable, so
memory requirement may be high - Implications?
- How much CPU/RAM does a web server use?
- How bad is bad? 1 increase 1000 increase?
- How does application runtime overhead influence
service?
19Discussion Applications
- Attack identification
- Use light-weight IPS
- Replay attack on instrumented version to identify
attack - Debugging tool
- Testing and debugging usually dont have lower
performance demands
20Memory Level Monitoring for Detecting Illegal
Writes
- Ongoing Research
- by
- Emre Can Sezer