Hi!! In this post I will describe how I managed to debug the DriverEntry routine of a driver for which I didn´t have the symbols.
As it is explained here, the DriverEntry name is not fixed across drivers, and you can choose any name you want. What makes a routine the initial one, is precicely the INIT keyword, and when the driver is compiled, the compiler creates a section called "optional" embedded in the driver where it is stored this address in an entry labeled "AddressOfEntryPoint". So all we have to do is find this address and insert a breakpoint in WinDBG.
To do that I used the following utility. Install it, open your driver and there you have:
Now you can insert a new breakpoint with: bp YouDriver+0x000bb09c, or if the driver you want to debug is loaded at boot time, reboot your computer and when WinDbg hits use: bu YouDriver+0x000bb09c.
If everything went fine you should run into a breakpoint inside function ioploaddriver from the Windows Kernel.
Hope it helps! As always, if you find any bug or want to contribute just send a comment. Thanks a lot!
lunes, 29 de octubre de 2012
jueves, 25 de octubre de 2012
Essential books
Hi! This is just a list of books I have or I plan to have ;) . I will update if I remember or find a new interesting book. In the meantime, please send a comment to suggest any book you think I'd like. Thanks a lot!!
Windows
Windows
- Windows Internals
- Windows NT File System Internals
- Advanced Windows Debugging
- Programming Win95
Linux
- Understanding the Linux Kernel
- Linux Device Drivers
- Embedded Linux
Programming
- C++ Programming Language
Electronics
- Design of Analog CMOS Integrated Circuits
- Microelectronics Circuits
- Digital Integrated Circuits
- RF Design of CMOS Radio Frequency Integrated Circuits
- Analog Integrated Circuit Design
- Wideband Amplifiers
- Microwave Engineering
- Solid State Electronic Devices
Books I'd like to read:
- What Makes It Page?: The Windows 7 (x64) Virtual Memory Manager
- The Rootkit Arsenal: Escape and Evasion in the Dark Corners of the System 2e
domingo, 21 de octubre de 2012
How to install SVN(subversion) and TortoiseSVN
Hi In this post I describe the steps I took to install SVN in my Raspberry Pi. Please note that I am not an expert, so send any comments you may have with suggestions to improve it.
For anyone working on a project, the advantages of having a repository are countless. To me, one of the aspects I like most of SVN is the log it makes, where you can see how a certain file has been changing in time. This lets you find who did certain thing, when and how. I can´t stress out how valuable this information is to me!
These steps are for a Debian based distro, but should work under others if you adapt the install procedure, and of course, this is not limited to Raspberry.
First of all you have to install the subversion package:
sudo apt-get install subversion
Then you should create a new user account to use SVN and change some permissions:
useradd svn
usermod -a -G svn pi #add usr pi to svn group
passwd svn #change password
Finally you can create a create a repository:
svnadmin create test
chown -R svn:svn test
chmod -R g+w test
At this point SVN is installed on your system and you should be able to use it as usual. The remaining part is just installing TortoiseSVN and connect to an existing repo. To show how to do that, let´s connecto to the test repo we've just created:
- Right click in the folder you want to check out the new repo.
- Click on SVN Checkout
- Type the following address: svn+ssh://pi@192.168.1.17/<absolute path to yout repo>
You have to change the local IP or host name to point to the server where you installed SVN and your username (I used pi for this example). Something that is worth mentioning is that the path to your repo in the previous address must be absolute (I mean /home/John/Projects/ProjectX) since it is passed as is to the ssh server.
If everything is working fine you'll notice there is still something very annoying to fix, the being asked twice or three times for the password thing!! To do so, just follow this link, and of course, if you have any question or difficulties, just send a comment!
Thanks a lot!
Presentation
Hi! This is my new blog where I will write about the projects I work in my free time. Please feel free to send any comments, suggestions, bugs, ideas, ... you find. Thanks a lot!
If you want to know something about me, I am an engineer whose main hobbies are outdoor sports, microcontrollers, OS, electronics, electric guitar, ... (actually too many hobbies). I work for a security software company as a Driver Developer and low level researcher.
If you want to know something about me, I am an engineer whose main hobbies are outdoor sports, microcontrollers, OS, electronics, electric guitar, ... (actually too many hobbies). I work for a security software company as a Driver Developer and low level researcher.
HMC5883L
Hi! In this post I am writing about the 3 axis digital compass IC HMC5883L. This is a cheap IC which gives the magnetic field direction and, as its name suggests, can be used to build an electronic compass. All information about this IC can be found in the datasheet.
If you plan on using this device I strongly suggest you to buy a board that includes all the necessary electronics, that is capacitors, resistors, maybe a LDO, ... that way you will save lot of time and even some money. Here is a photograph of mine:
To connect the device to our controller the key aspect of this device is the interface used, which is the I2C serial bus. That means you need 2 dedicated writes, one for SDA and another for SCL and don´t forget the pull-up resistors!
When the device is properly connected to the controller you can start communicating with it, which as you know is done writing and reading to and from internal registers. The simplest set of commands to configure and start reading the sensor are the following:
Once you have configured the device and you have checked it is properly working, it´s time to read the output. To do that we have to bear in mind a few aspects, first each axis has two output registers, second the address register is self incremented when you read one such register,third you have to read al output registers to perform a new measurement (if not the output registers will no longer update).
To summarize it all and provide a basic piece of code for this device, let´s write both the initialization and read routines. I have chosen CSS PICC compliler becasuse it is extremely easy to use and to understand so it is easily portable to any other C compiler (and even to assembler):
char Configure()
{
unsigned char byte1;
i2c_start();
i2c_write(ADDR | WRITE);
i2c_write(0x00); //set Configuration Register A
i2c_write(0x78);
i2c_stop();
i2c_start();
i2c_write(ADDR | WRITE);
i2c_write(0x01); //set Configuration Register B
i2c_write(0xA0);
i2c_stop();
i2c_start();
i2c_write(ADDR | WRITE);
i2c_write(0x02); //set Mode Register
i2c_write(0x00);
i2c_stop();
i2c_start();
i2c_write(ADDR | WRITE);
i2c_write(0x0A); //set address register to register 0xA
i2c_stop();
delay_ms(10);
i2c_start();
i2c_write(ADDR | READ);
byte1=i2c_read(0); //read Identification Register
i2c_stop();
if(0x48 == byte1)
return 1;
else
return 0;
}
typedef struct
{
unsigned int8 x;
pnt.z=i2c_read();
pnt.y=i2c_read();
I have tried to keep this code simple and nice, no error or collition checkings are performed so if you connect more than one device to the same I2C bus, I'd reccomend you to do that.
So far I have shown how to to some basic operations with this device, but I have not shown how to obtain the real direction. I hope I'll have some time to draw some pictures to explain that, in the meantime, if you have any question or find something wrong (I'm not much of an expert) just send a comment please!
If you plan on using this device I strongly suggest you to buy a board that includes all the necessary electronics, that is capacitors, resistors, maybe a LDO, ... that way you will save lot of time and even some money. Here is a photograph of mine:
To connect the device to our controller the key aspect of this device is the interface used, which is the I2C serial bus. That means you need 2 dedicated writes, one for SDA and another for SCL and don´t forget the pull-up resistors!
When the device is properly connected to the controller you can start communicating with it, which as you know is done writing and reading to and from internal registers. The simplest set of commands to configure and start reading the sensor are the following:
- Write 0x78 to resgister 0x00. This sets 8 samples averaged per measurement, output rate of 75Hz and normal measurement configuration.
- Write 0xA0 to register 0x01. This sets the gain to 4.7
- Write 0x00 to register 0x02. This sets the device operating mode to continuous-Measurement mode.
One usefull thing you can do to ensure the conmmunication is properly initialized and everything is going fine is to read the identifications registers. In this IC there are three of them, so you can choose which one to read, or read them all!
To do that just issue a start command, after that a write operation to address 0x0A, then a stop command. Up to now we have changed the address register to Identification Register A. To read the content, send a start command, then read 8 bits with NO-ACK and send a stop command. The data just read should be 0x48 or character 'H', if it is not (it will likely be 0x00), there is a problem with either the software or hardware.
It´s worth noting something from the previous example, To set the address register, which is the register that contains the address of the current register to be read from or written to, just issue a write opetation to the register address you want to access with no data following the address.
It´s worth noting something from the previous example, To set the address register, which is the register that contains the address of the current register to be read from or written to, just issue a write opetation to the register address you want to access with no data following the address.
Once you have configured the device and you have checked it is properly working, it´s time to read the output. To do that we have to bear in mind a few aspects, first each axis has two output registers, second the address register is self incremented when you read one such register,third you have to read al output registers to perform a new measurement (if not the output registers will no longer update).
To summarize it all and provide a basic piece of code for this device, let´s write both the initialization and read routines. I have chosen CSS PICC compliler becasuse it is extremely easy to use and to understand so it is easily portable to any other C compiler (and even to assembler):
char Configure()
{
unsigned char byte1;
i2c_start();
i2c_write(ADDR | WRITE);
i2c_write(0x00); //set Configuration Register A
i2c_write(0x78);
i2c_stop();
i2c_start();
i2c_write(ADDR | WRITE);
i2c_write(0x01); //set Configuration Register B
i2c_write(0xA0);
i2c_stop();
i2c_start();
i2c_write(ADDR | WRITE);
i2c_write(0x02); //set Mode Register
i2c_write(0x00);
i2c_stop();
i2c_start();
i2c_write(ADDR | WRITE);
i2c_write(0x0A); //set address register to register 0xA
i2c_stop();
delay_ms(10);
i2c_start();
i2c_write(ADDR | READ);
byte1=i2c_read(0); //read Identification Register
i2c_stop();
if(0x48 == byte1)
return 1;
else
return 0;
}
And the routine to actually read the output:
typedef struct
{
unsigned int8 x;
unsigned int8 y;
unsigned int8 z;
}point;
signed int16 Read()
{
point pnt;
i2c_start();
i2c_write(ADDR | WRITE);
i2c_write(0x03); //Data output X. Remember address register is self incremented
i2c_stop();
i2c_start();
i2c_write(ADDR | READ);
pnt.x=i2c_read();
(pnt.x)<<=8;
(pnt.x)|=i2c_read(); //read X component
pnt.z=i2c_read();
(pnt.z)<<=8;
(pnt.z)|=i2c_read(); //read Z component
pnt.y=i2c_read();
(pnt.y)<<=8;
(pnt.y)|=i2c_read(0); //read Y component
i2c_stop();
//convert pnt to direction TO BE DONE
return PointToDirection(&pnt);
//convert pnt to direction TO BE DONE
return PointToDirection(&pnt);
}
I have tried to keep this code simple and nice, no error or collition checkings are performed so if you connect more than one device to the same I2C bus, I'd reccomend you to do that.
So far I have shown how to to some basic operations with this device, but I have not shown how to obtain the real direction. I hope I'll have some time to draw some pictures to explain that, in the meantime, if you have any question or find something wrong (I'm not much of an expert) just send a comment please!
sábado, 20 de octubre de 2012
Kernel: In search of the exception routines
Hi!! In this post I will show where the exception routines reside in memory for x86 platforms. Exception routines play an essencial role in the system operation as they allow it to attend for different internal events, such as page fault. When the system tries to reference a memory address that is not currently in physical memory (that is, it is backed up by virtual memory and resides on disk), the MMU generates a page fault exception (in Windows kernel the service routine for that trap is KiTrap0E), so that the OS can recover that address from disk.
Another example is the divide by 0 exception, which allows the system to recover from an anomalous operation.
There are three types of exceptions: traps, aborts and faults. Traps are exceptions whose execution continues after the instruction that generated the trap once it is processed, as an example we have the int 3 for debugging.
Faults are exception that can be corrected, and then the instruction that generated the fault can be re-executed. As an example we have page fault commented above.
Finally aborts are severe exceptions such as hardware problems. Usually the final cause of the exception is not known, that is, a problem is detected but it is unknown where it originated.
The routines called by the CPU when a certain exception occurs are called Exception Service Routines. Exception Service Routines are similar to Interrupt Service Routines with the difference that they are generated by the CPU, so they are stored in the same memory structure called IDT (Interrupt Descriptor Table).
In protected mode, Intel platform has up to 256 interrupt entries, each one is represented by an 8 bytes structure in the IDT, which means the size of the whole IDT is 2KB. The processor knows the base address of the IDT through the IDTR register.
The IDT can have several types of entries being the following:
So now, all we have to do to find the Service Routine for the divide by 0 exception (vector 0) is get the first 8 bytes of the memory pointed to by the IDTR register:
kd> dd idtr L 2
8003f400 0008e19c 80538e00
Rearranging it to fit to previous image we have:
8053 8e00
0008 e19c
So the routine address is 0x8053e19c, and the segment selector is 8. We can also check this entry is an interrupt gate looking the sixth byte: 0x8e. This means it is a 32-bits (D=1) interrupt gate with 0 priviledge (DPL=00).
Finally we check the address we got:
kd> ln 0x8053e19c
(8053e19c) nt!KiTrap00 | (8053e268) nt!Dr_kit1_a
Exact matches:
nt!KiTrap00
Or equivalently:
kd> !idt 0
Dumping IDT:
00: 8053e19c nt!KiTrap00
We can also check the segment selector:
It shows segment selector 8 is for kernel code, as we expected.
As a further example we can find the Service Rotine for Page Fault (Vector14):
kd> dd idtr+8*e L2
8003f470 00080450 80548e00
kd> ln 80540450
(80540450) nt!KiTrap0E | (805406d4) nt!Dr_kitf_a
Exact matches:
nt!KiTrap0E = <no type information>
Before I finish this post there is something else I think is worth mentioning, if you want to find a ISR in the IDT, just add 32 to the interrupt number you want to find, that is, if you want to find interrupt 0 ISR, just get the 32sd entry in the IDT.
This post is mainly aimed to myself ;), but if someone finds any bug or something is not clear enough, please send a comment so I can fix it. Thanks!!
Another example is the divide by 0 exception, which allows the system to recover from an anomalous operation.
There are three types of exceptions: traps, aborts and faults. Traps are exceptions whose execution continues after the instruction that generated the trap once it is processed, as an example we have the int 3 for debugging.
Faults are exception that can be corrected, and then the instruction that generated the fault can be re-executed. As an example we have page fault commented above.
Finally aborts are severe exceptions such as hardware problems. Usually the final cause of the exception is not known, that is, a problem is detected but it is unknown where it originated.
The routines called by the CPU when a certain exception occurs are called Exception Service Routines. Exception Service Routines are similar to Interrupt Service Routines with the difference that they are generated by the CPU, so they are stored in the same memory structure called IDT (Interrupt Descriptor Table).
In protected mode, Intel platform has up to 256 interrupt entries, each one is represented by an 8 bytes structure in the IDT, which means the size of the whole IDT is 2KB. The processor knows the base address of the IDT through the IDTR register.
The IDT can have several types of entries being the following:
- Interrupt Gate
- Task Gate
- Trap Gate
So now, all we have to do to find the Service Routine for the divide by 0 exception (vector 0) is get the first 8 bytes of the memory pointed to by the IDTR register:
kd> dd idtr L 2
8003f400 0008e19c 80538e00
Rearranging it to fit to previous image we have:
8053 8e00
0008 e19c
So the routine address is 0x8053e19c, and the segment selector is 8. We can also check this entry is an interrupt gate looking the sixth byte: 0x8e. This means it is a 32-bits (D=1) interrupt gate with 0 priviledge (DPL=00).
Finally we check the address we got:
kd> ln 0x8053e19c
(8053e19c) nt!KiTrap00 | (8053e268) nt!Dr_kit1_a
Exact matches:
nt!KiTrap00
Or equivalently:
kd> !idt 0
Dumping IDT:
00: 8053e19c nt!KiTrap00
We can also check the segment selector:
It shows segment selector 8 is for kernel code, as we expected.
As a further example we can find the Service Rotine for Page Fault (Vector14):
kd> dd idtr+8*e L2
8003f470 00080450 80548e00
kd> ln 80540450
(80540450) nt!KiTrap0E | (805406d4) nt!Dr_kitf_a
Exact matches:
nt!KiTrap0E = <no type information>
Before I finish this post there is something else I think is worth mentioning, if you want to find a ISR in the IDT, just add 32 to the interrupt number you want to find, that is, if you want to find interrupt 0 ISR, just get the 32sd entry in the IDT.
This post is mainly aimed to myself ;), but if someone finds any bug or something is not clear enough, please send a comment so I can fix it. Thanks!!
Suscribirse a:
Entradas (Atom)