The vulnerability lie in dwgutil.cpp
void dwgCompressor::decompress18(duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize){//对一个缓冲区的数据进行解压
...............................................................
...............................................................
...............................................................
// The vulnerability Point !!!!!!!!
//when rpos < compOffset , j could be a large value.
for (duint32 i=0, j= rpos - compOffset -1; i < compBytes; i++) { // 出现 rpos < compOffset, 会出现负数,越界读
bufD[rpos++] = bufD[j++];
}
...............................................................
...............................................................
As you can see , j's type is duint32 ( unsigned int ). when rpos < compOffset , j could be a negative number . Because j is unsigned , j will be a large value (:like 0xffffffff)
Let see in gdb
----------------------------------registers-----------------------------------]
RAX: 0xa98
RBX: 0x7fffffffd9a0 --> 0x793330 --> 0xbab937a8292b0800
RCX: 0xa ('\n')
RDX: 0x325
RSI: 0x326
RDI: 0x7fffffffd9a0 --> 0x793330 --> 0xbab937a8292b0800
RBP: 0x2d36 ('6-')
RSP: 0x7fffffffd7c0 --> 0x7
RIP: 0x4a1817 (<dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+455>: not ebp)
R8 : 0x793330 --> 0xbab937a8292b0800
R9 : 0x1c
R10: 0x15b0
R11: 0x0
R12: 0x0
R13: 0x6968 ('hi')
R14: 0x7401
R15: 0x857
EFLAGS: 0x283 (CARRY parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x4a180b <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+443>: sub r13d,r12d
0x4a180e <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+446>: cmp ecx,r13d
0x4a1811 <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+449>: ja 0x4a19eb <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+923>
=> 0x4a1817 <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+455>: not ebp
0x4a1819 <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+457>: add ebp,eax
0x4a181b <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+459>: test ecx,ecx
0x4a181d <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+461>: lea edi,[rbp+rcx*1+0x0]
0x4a1821 <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+465>: jne 0x4a182d <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+477>
Breakpoint 3, 0x00000000004a1817 in dwgCompressor::decompress18 (this=this@entry=0x7fffffffd9a0, cbuf=cbuf@entry=0x793330 "", dbuf=dbuf@entry=0x7b2e30 "+)\250\067\271\272\031\030\030\230(97\270\032\034\214", csize=csize@entry=0x857, dsize=dsize@entry=0x7400)
at intern/dwgutil.cpp:204
204 if (remaining < compBytes){
gdb-peda$
eax is rpos and ebp is compOffset , you can see rpos(0xa98) < compOffset (0x2d36). then j could be 0xffffdd61 , crash !!!!!
[-------------------------------------code-------------------------------------]
0x4a1831 <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+481>: lea ecx,[rax+0x1]
0x4a1834 <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+484>: mov DWORD PTR [rbx+0x1c],ecx
0x4a1837 <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+487>: lea ecx,[rbp+0x1]
=> 0x4a183a <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+490>: movzx esi,BYTE PTR [rdx+rbp*1]
0x4a183e <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+494>: cmp ecx,edi
0x4a1840 <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+496>: mov BYTE PTR [rdx+rax*1],sil
0x4a1844 <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+500>: jne 0x4a1828 <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+472>
0x4a1846 <dwgCompressor::decompress18(unsigned char*, unsigned char*, unsigned int, unsigned int)+502>: xor ecx,ecx
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffd7c0 --> 0x7
0008| 0x7fffffffd7c8 --> 0xaf7b8da0e
0016| 0x7fffffffd7d0 --> 0x4e300d --> 0xa736574796220 (' bytes\n')
0024| 0x7fffffffd7d8 --> 0x7fffffffd970 --> 0x78e7e8 --> 0xa73657479000a ('\n')
0032| 0x7fffffffd7e0 --> 0x78e7e8 --> 0xa73657479000a ('\n')
0040| 0x7fffffffd7e8 --> 0x47edb8 (<DRW_dbg::print(std::string)+40>: mov rax,QWORD PTR [rsp+0x10])
0048| 0x7fffffffd7f0 --> 0x0
0056| 0x7fffffffd7f8 --> 0x7fffffffd9e0 --> 0x78f7e0 --> 0x7fff00000001
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
The vulnerability lie in
dwgutil.cppAs you can see , j's type is
duint32(unsigned int). whenrpos < compOffset,jcould be a negative number . Because j isunsigned, j will be a large value (:like0xffffffff)Let see in gdb
eaxisrposandebpiscompOffset, you can see rpos(0xa98) < compOffset (0x2d36). then j could be0xffffdd61, crash !!!!!