Security Ripcord


Assembly Debugging with VTrace

Although my last foray into assembly via a Hello World program was helpful, it only scratched the surface. I was thinking about moving onto some user input programs next when I realized that it might be more helpful if I learned how to do some quick arithmetic using assembly. To do this I located some additional resources to help my understanding of assembly.

Together with my old version of Hello World I created an assembly program that would print out a “Number is 0″ and then “Number is 1″. My intention was to set a register to 0 and then to increment the register so that it equaled 1. The following is the program.

DISCLAIMER UPDATE:  The following assembly code does not work.  That is the point.  The walk through after the code, however, does help.

// Assembly Arithmetics

.data
NUMS:
.string “Number is ”
NUMSLEN:
.short $-NUMS
EOL:
.string “\n”
EOLLEN:
.short $-EOL

.text
.globl _start

_start:
//Print NUMSTRING
movl $4,%eax
movl $1,%ebx
movl $NUMS,%ecx
movl $NUMSLEN,%edx
int $0×80

//Make a register equal to zero and print
xor %ecx,%ecx
xor %edx,%edx
inc %edx
int $0×80

//Print EOL
movl $EOL,%ecx
movl $EOLLEN,%edx
int $0×80

//Print NUMSTRING
movl $NUMS,%ecx
movl $NUMSLEN,%edx
int $0×80

//Increment register from zero to one
xor %ecx,%ecx
xor %edx,%edx
inc %ecx
inc %edx
int $0×80

//Print EOL
movl $EOL,%ecx
movl $EOLLEN,%edx
int $0×80

//Exit
ret

To help me compile this I also created a quick Makefile.

arth.as: arth.as.o
ld arth.as.o -o arth.as.exe
arth.as.o: arth.as.s
as arth.as.s -o arth.as.o

This Makefile allowed me to just type “make” every time that I needed to make a change to the assembly program. This happened several times before I came to the assembly program above. Once I had the executable, I thought I was good to go. Unfortunately.

bt as # ls
Makefile arth.as.s
bt as # make
as arth.as.s -o arth.as.o
ld arth.as.o -o arth.as.exe
bt as # ls
Makefile arth.as.exe* arth.as.o arth.as.s
bt as # ./arth.as.exe
Number is

Segmentation fault
bt as #

Dang ol’ Seg fault. What do I do now? Well, I was going to start moving things around and checking against other simple programs available via Google when I remembered that I could step through the executable using VTrace. After a little trial and error I taught myself to attach to the executable, step through each instruction, pull all of the registry values, pull selected registry values, and run the program all of the way through. The following output shows each of these steps. You will notice that I decided to start using several arrays to help me consistently output the values of the registers.

IDLE 1.1.3
>>> import vtrace
>>> tr = vtrace.getTrace()
>>> tr.execute(’/root/Development/test_programs/c/misc/as/c_stuff.as.exe’)
>>> tr.getPid()
11683
>>> arrRegs = ['eax','ebx','ecx','edx']
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 0
ebx : 0
ecx : 0
edx : 0
>>> arrAllRegs = tr.getRegisters()
>>> for key in arrAllRegs:
print “%s : %s” % (key,arrAllRegs[key])

debug1 : 0
debug0 : 0
debug3 : 0
debug2 : 0
debug5 : 0
debug4 : 0
debug7 : 0
debug6 : 0
edi : 0
eax : 0
cs : 115
fs : 0
ebp : 0
__fs : 0
__cs : 0
gs : 0
edx : 0
ebx : 0
ds : 123
__es : 0
ecx : 0
eip : 134512756
esp : 3213311088
ss : 123
__ds : 0
__ss : 0
__gs : 0
eflags : 2097798
es : 123
orig_eax : 11
esi : 0
>>> tr.run()
>>> arrAllRegs = tr.getRegisters()
>>> for key in arrAllRegs:
print “%s : %s” % (key,arrAllRegs[key])

debug1 : 0
debug0 : 0
debug3 : 0
debug2 : 0
debug5 : 0
debug4 : 0
debug7 : 0
debug6 : 0
edi : 0
eax : 4294967258
cs : 115
fs : 0
ebp : 0
__fs : 0
__cs : 0
gs : 0
edx : 134516943
ebx : 1
ds : 123
__es : 0
ecx : 134516941
eip : 1
esp : 3213311092
ss : 123
__ds : 0
__ss : 0
__gs : 0
eflags : 2163202
es : 123
orig_eax : 4294967295
esi : 0
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258 <- NOTE: Remember these values for later
ebx : 1
ecx : 134516941
edx : 134516943
>>> tr.detach()
>>> tr.getPid()
0
>>>

Okay, that didn’t help. I guess I need to step through using “tr.stepi()” and output the registry value after each step. Let’s see if it helps. I have inserted the assembly code as NOTE: throughout the output.

IDLE 1.1.3
>>> import vtrace
>>> tr=vtrace.getTrace()
>>> tr.getPid()
0
>>> tr.execute(’/root/Development/test_programs/c/misc/as/arth.as.exe’)
>>> tr.getPid()
14727
>>> arrAllRegs = tr.getRegisters()
>>> for key in arrAllRegs:
print “%s : %s” % (key,arrAllRegs[key])

debug1 : 0
debug0 : 0
debug3 : 0
debug2 : 0
debug5 : 0
debug4 : 0
debug7 : 0
debug6 : 0
edi : 0
eax : 0
cs : 115
fs : 0
ebp : 0
__fs : 0
__cs : 0
gs : 0
edx : 0
ebx : 0
ds : 123
__es : 0
ecx : 0
eip : 134512756
esp : 3220532048
ss : 123
__ds : 0
__ss : 0
__gs : 0
eflags : 2097798
es : 123
orig_eax : 11
esi : 0
>>> arrRegs = ['eax','ebx','ecx','edx']
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 0 <- NOTE: All registers appear to start clean
ebx : 0
ecx : 0
edx : 0
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4 <- NOTE: movl $4,%eax
ebx : 0
ecx : 0
edx : 0
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4
ebx : 1 <- NOTE: movl $1,%ebx
ecx : 0
edx : 0
>>> tr.stepi()
>>>
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4
ebx : 1
ecx : 134516928 <- NOTE: movl $NUMS,%ecx
edx : 0
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4
ebx : 1
ecx : 134516928
edx : 134516939 <- NOTE: movl $NUMSLEN,%edx
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 2048 <- NOTE: int $0×80 I’m not sure why this register changed UPDATE: Confirmed, this register is changed with the result of “int $0×80″, which means the next “int $0×80″ will do the system call assigned to 2048 or $0×800
ebx : 1
ecx : 134516928
edx : 134516939
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 2048
ebx : 1
ecx : 0 <- NOTE: xor %ecx,%ecx
edx : 134516939
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 2048
ebx : 1
ecx : 0
edx : 0 <- NOTE: xor %edx,%edx
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 2048
ebx : 1
ecx : 0
edx : 1 <- NOTE: inc %edx
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258 <- NOTE: int $0×80 Okay, this is probably the segfault, but VTrace doesn’t stop stepping here
ebx : 1
ecx : 134516941 <- NOTE: movl $EOL,%ecx I’m also not sure why it seems like it stepped twice and executed the next instruction
edx : 1
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258
ebx : 1
ecx : 134516941
edx : 134516943 <- NOTE: movl $EOLLEN,%edx
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258
ebx : 1
ecx : 134516928 <- NOTE: movl $NUMS,%ecx
edx : 134516943
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258
ebx : 1
ecx : 134516928
edx : 134516939 <- NOTE: movl $EOLLEN,%edx
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258
ebx : 1
ecx : 0 <- NOTE: xor %ecx,%ecx
edx : 134516939
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258
ebx : 1
ecx : 0
edx : 0 <- NOTE: xor %edx,%edx
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258
ebx : 1
ecx : 1 <- NOTE: inc %ecx
edx : 0
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258
ebx : 1
ecx : 1
edx : 1 <- NOTE: inc %edx
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258
ebx : 1
ecx : 134516941 <- NOTE: movl $EOL,%ecx
edx : 1
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258 <- NOTE: Complete run through stopped here
ebx : 1
ecx : 134516941
edx : 134516943 <- NOTE: movl $EOLLEN,%edx
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258
ebx : 1
ecx : 134516941
edx : 134516943
>>> tr.stepi()
>>> for i in arrRegs:
print “%s : %s” % (i,tr.getRegisterByName(i))

eax : 4294967258 <- NOTE: Step through stops here as well
ebx : 1
ecx : 134516941
edx : 134516943
>>> tr.detach()
>>> tr.getPid()
0
>>>

Not much help there. Basically, VTrace will step right through a segmentation fault. Although, now that I run through the program step by step I think I can see where the program failed. I guess the “int $0×80″ changes the register $eax. I believe this means that I have to reset this value before writing.

What still bothers me though is the fact that VTrace did not stop on the segmentation fault. I thought debuggers did this. That is when I realized that VTrace is not necessarily a debugger. Actually VDB is a debugger and I should have used that instead of troubleshooting with VTrace. I guess I could just reset the register before telling it to print, I think I’ll try VDB to see if it will help me identify the exact step where the executable stops.

More assembly soon!!

UPDATE: As I mentioned inline, the call “int $0×80″ writes it’s return value to %eax. This means that I will l have to update %eax with a decimal 4 every time I want to write out. Also, I have come to realize that whether I use VTrace, VDB, or GDB no debugger is going to help me overcome bad code. I guess I need a book because online resources don’t seem to be cutting it for me. I did find one resource that mentioned that the values in the registers are not necessarily ASCII and that they will need to be converted before being output. But then the same resource went straight into memory modification to write the number with the original string instead of outputting them one at a time like I have here. I’m going to try and get a grasp on this before I start delving into memory modification.

Go forth and do good things,

Don C. Weber



Help support my training and travel to security conferences. Get your SANS Training and GIAC Certifications through the Security Ripcord.

You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Reply