PANDA tracing with Windows guest

In a previous article, I covered tracing programs using PANDA in a Linux guest. This is made relatively easy by the fact that we can just boot a LiveDVD. In Windows, however, we need to install the OS onto a virtual hard drive to be able to boot into a guest. That makes the process a little different. We start in the same way, however:

1: Install PANDA on host

On a clean Ubuntu 18.04.03

$ sudo apt install git

# clone and build PANDA. This does download PANDA twice, but it's easy this way.

$ git clone https://github.com/panda-re/panda
$ cd panda/panda/scripts/
$ ./install_ubuntu.sh
$ cd panda/build/x86_64-softmmu

now we start to deviate from the previous process. Install qemu-utils and create a disk image to install windows on.

$ sudo apt install qemu-utils
$ qemu-img create -f qcow2 windisk.img 20G
$ ./panda-system-x86_64 --monitor stdio -m 4096 -hda windisk.img -cdrom winxpsp3.iso

Then, just install Windows. On subsequent boots, we won't need the cdrom

$ ./panda-system-x86_64 --monitor stdio -m 4096 -hda windisk.img 

2: Test Trace Execution


The --monitor stdio option kept the qemu command prompt open to receive commands and this is where we issue the command to start recording

(qemu) begin_record therecording
(qemu) writing snapshot:  ./therecording-rr-snp
opening nondet log for write: ./therecording-rr-nondet.log
end_record
(qemu) Time taken was: 7 seconds.
Checksum of guest memory: 0x4e5c394a

And at some point we end the recording

(qemu) end_record

This record can now be operated on. One possibility is to generate a movie showing what the GUI displayed during the recording session.

$ sudo apt install ffmpeg
$ ./panda-system-x86_64 -m 4096 -replay therecording -panda replaymovie 
$ ../../../../plugins/replaymovie/movie.sh
$ ffplay replay.mp4

And this can then be turned into an animated GIF, if you have need for that.

$ ffmpeg -y -i replay.mp4 -vf palettegen palette.png
$ ffmpeg -i replay.mp4 -i palette.png -lavfi paletteuse  out.gif

The animation below is the outcome of this recording.

3: Trace program execution

First, we test the OSI functionality

$ ./panda-system-x86_64 -m 4096 -replay tracerecording -os windows-32-xpsp3 -panda osi 
PANDA[core]:os_familyno=1 bits=32 os_details=xpsp3
PANDA[core]:initializing osi
PANDA[core]:loading required plugin wintrospection
PANDA[core]:initializing wintrospection
PANDA[core]:loading required plugin winxpx86intro
PANDA[core]:initializing winxpx86intro
loading snapshot
... done.
opening nondet log for read :  ./tracerecording-rr-nondet.log
./tracerecording-rr-nondet.log:   546763745 instrs total.
tracerecording:     5467641 (  1.00%) instrs.    0.37 sec.  0.38 GB ram.

[ ... ]

tracerecording:   535828471 ( 98.00%) instrs.   15.04 sec.  0.51 GB ram.
tracerecording:   541296112 ( 99.00%) instrs.   15.23 sec.  0.51 GB ram.
./tracerecording-rr-nondet.log:  log is empty.
./tracerecording-rr-nondet.log:  log is empty.
Time taken was: 15 seconds.
Stats:
RR_INPUT_1 number = 0, size = 0 bytes
RR_INPUT_2 number = 0, size = 0 bytes
RR_INPUT_4 number = 54277, size = 759878 bytes
RR_INPUT_8 number = 54775, size = 985950 bytes
RR_INTERRUPT_REQUEST number = 25123, size = 351722 bytes
RR_EXIT_REQUEST number = 0, size = 0 bytes
RR_SKIPPED_CALL number = 45823, size = 12848530 bytes
RR_END_OF_LOG number = 1, size = 10 bytes
RR_PENDING_INTERRUPTS number = 0, size = 0 bytes
RR_EXCEPTION number = 0, size = 0 bytes
max_queue_len = 47
Checksum of guest memory: 0xf0ed926
Replay completed successfully
Unloading wintrospection plugin
Exiting cpu_handle_execption loop

And with that working, we can perform trace extraction

$ ./panda-system-x86_64 -m 4096 -replay tracerecording -os windows-32-xpsp3 -panda osi -panda coverage:filename=trace_coverage.csv,mode=process


PANDA[core]:os_familyno=1 bits=32 os_details=xpsp3
PANDA[coverage]:adding argument filename=trace_coverage.csv.
PANDA[coverage]:adding argument mode=process.
PANDA[core]:initializing osi
PANDA[core]:loading required plugin wintrospection
PANDA[core]:initializing wintrospection
PANDA[core]:loading required plugin winxpx86intro
PANDA[core]:initializing winxpx86intro
PANDA[core]:initializing coverage
PANDA[coverage]:output file name ch28_coverage.csv
PANDA[coverage]:file buffer_size 8192
PANDA[coverage]:log all records DISABLED
PANDA[coverage]:mode process
PANDA[core]:loading required plugin osi
PANDA[core]:/home/jan/Downloads/panda/panda/scripts/panda/build/x86_64-softmmu/panda/plugins/panda_osi.so already loaded
PANDA[coverage]:start disabled DISABLED
loading snapshot
... done.
opening nondet log for read :  ./tracerecording-rr-nondet.log
./tracerecording-rr-nondet.log:   546763745 instrs total.
tracerecording:     5467641 (  1.00%) instrs.    1.56 sec.  0.38 GB ram.
tracerecording:    10935276 (  2.00%) instrs.    2.69 sec.  0.38 GB ram.

[ ... ]

tracerecording:   535828471 ( 98.00%) instrs.  188.04 sec.  0.55 GB ram.
tracerecording:   541296112 ( 99.00%) instrs.  189.98 sec.  0.55 GB ram.
./tracerecording-rr-nondet.log:  log is empty.
./tracerecording-rr-nondet.log:  log is empty.
Time taken was: 192 seconds.
Stats:
RR_INPUT_1 number = 0, size = 0 bytes
RR_INPUT_2 number = 0, size = 0 bytes
RR_INPUT_4 number = 54277, size = 759878 bytes
RR_INPUT_8 number = 54775, size = 985950 bytes
RR_INTERRUPT_REQUEST number = 25123, size = 351722 bytes
RR_EXIT_REQUEST number = 0, size = 0 bytes
RR_SKIPPED_CALL number = 45823, size = 12848530 bytes
RR_END_OF_LOG number = 1, size = 10 bytes
RR_PENDING_INTERRUPTS number = 0, size = 0 bytes
RR_EXCEPTION number = 0, size = 0 bytes
max_queue_len = 47
Checksum of guest memory: 0xf0ed926
Replay completed successfully
Unloading wintrospection plugin
Exiting cpu_handle_execption loop

We can now perform and evaluate execution of programs as detailed before in PANDA for code coverage with IDA pro

Appendix: file exchange

Bridged networking is a pain. I prefer to mount the drive image . To mount the file in the host after exiting PANDA

$ sudo mkdir /media/vmshare
$ sudo modprobe nbd max_part=63
$ sudo qemu-nbd -c /dev/nbd0 windisk.img
$ sudo mount /dev/nbd0p1 /media/vmshare/

and to unmount the file

$ sudo umount /media/vmshare

References: