RBS EverFocus Electronics Corp EverNet3 ActiveX Control Multiple Vulnerabilities of 28

Similar documents
RBS EverFocus Electronics Corp EPlusOcx ActiveX Control Multiple Stack Buffer Overflows of 10

RBS Asante VMS ActiveXCoat ActiveX Control ConnectToVMS() Method Heap Buffer Overflow of 7

RBS S Pocketnet Tech MediaViewer ActiveX Control Multiple Buffer Overflow Vulnerabilities of 14

RBS of 6

RBS OpenEMR Multisite Setup Improper Access Restriction Remote Code Execution of 5

SA30285 / CVE

IBM Global Services. Reversing C++ Paul Vincent Sabanal X-Force R&D Mark Vincent Yason X-Force R&D. IBM Internet Security Systems Ahead of the threat.

RBS Axis Products Management Web Interface Multiple Vulnerabilities of 9

RBS NetGain Enterprise Manager Multiple Vulnerabilities of 11

SA31675 / CVE

RBS NetGain Enterprise Manager Web Interface Multiple Vulnerabilities of 9

In executable we have several anti-debugging, anti-tracing and anti-patching tricks:

RBS Rockwell Automation FactoryTalk Services Platform RNADiagnostics Module Missing Size Field Validation Remote Denial of Service.

Reverse Engineering II: The Basics

SA33901 / CVE

Stack -- Memory which holds register contents. Will keep the EIP of the next address after the call

Silent Signal Kft. Web: Budapest,

CSC 405 Computer Security Reverse Engineering Part 1

Flare- On 4: Challenge 11 Solution - covfefe.exe

Practical Malware Analysis

CNIT 127: Exploit Development. Ch 1: Before you begin. Updated

EECE.3170: Microprocessor Systems Design I Summer 2017 Homework 4 Solution

CS412/CS413. Introduction to Compilers Tim Teitelbaum. Lecture 21: Generating Pentium Code 10 March 08

CSC 591 Systems Attacks and Defenses Reverse Engineering Part 1

Abysssec Research. 1) Advisory information. 2) Vulnerable version. : Microsoft Excel SxView Record Parsing Memory Corruption

SA28083 / CVE

Finding 0-days by Using VulnHunt

Reverse Engineering II: Basics. Gergely Erdélyi Senior Antivirus Researcher

Reverse Engineering II: The Basics

x86 assembly CS449 Fall 2017

Operation RussianDoll: Adobe & Windows Zero Day Exploits LikelyLeveraged by Russia s APT28 in Highly Targeted Attack

Abysssec Research. 1) Advisory information. 2) Vulnerable version

16.317: Microprocessor Systems Design I Fall 2014

CMSC 313 COMPUTER ORGANIZATION & ASSEMBLY LANGUAGE PROGRAMMING

Autodesk AutoCAD DWG-AC1021 Heap Corruption

X86 Addressing Modes Chapter 3" Review: Instructions to Recognize"

Assembly Language Programming: Procedures. EECE416 uc. Charles Kim Howard University. Fall

16.317: Microprocessor Systems Design I Fall 2015

Buffer Overflows Defending against arbitrary code insertion and execution

Abysssec Research. 1) Advisory information. 2) Vulnerability Information. Class 1- Stack overflow. Impact

Objectives. ICT106 Fundamentals of Computer Systems Topic 8. Procedures, Calling and Exit conventions, Run-time Stack Ref: Irvine, Ch 5 & 8

Betriebssysteme und Sicherheit Sicherheit. Buffer Overflows

12 th January MWR InfoSecurity Security Advisory. WebSphere MQ xcsgetmem Heap Overflow Vulnerability. Contents

Introduc)on to x86 Architecture

administrivia today start assembly probably won t finish all these slides Assignment 4 due tomorrow any questions?

Flare- On 4: Challenge 12 Solution [missing]

Data Exfiltration Techniques

Basic Pentium Instructions. October 18

CSC 405 Computer Security Reverse Engineering

security audit Oracle case Cesar Cerrudo

Reverse Engineering Low Level Software. CS5375 Software Reverse Engineering Dr. Jaime C. Acosta

Microsoft Office Protected-View Out-Of- Bound Array Access

Scott M. Lewandowski CS295-2: Advanced Topics in Debugging September 21, 1998

16.317: Microprocessor Systems Design I Spring 2015

CSC 2400: Computer Systems. Towards the Hardware: Machine-Level Representation of Programs

Rev101. spritzers - CTF team. spritz.math.unipd.it/spritzers.html

complement) Multiply Unsigned: MUL (all operands are nonnegative) AX = BH * AL IMUL BH IMUL CX (DX,AX) = CX * AX Arithmetic MUL DWORD PTR [0x10]

EECE.3170: Microprocessor Systems Design I Summer 2017

Hacking the Packer. Introduction

FLARE-On 4: Challenge 3 Solution greek_to_me.exe

CNIT 127: Exploit Development. Ch 2: Stack Overflows in Linux

CMPSC 497 Buffer Overflow Vulnerabilities

Reverse Engineering I: Introduction

MWR InfoSecurity Security Advisory. IBM WebSphere MQ - rridecompress Remote Denial of Service Vulnerability. 4th March 2010

Secure Programming Lecture 3: Memory Corruption I (Stack Overflows)

Islamic University Gaza Engineering Faculty Department of Computer Engineering ECOM 2125: Assembly Language LAB. Lab # 7. Procedures and the Stack

CS241 Computer Organization Spring 2015 IA

SYSTEM CALL IMPLEMENTATION. CS124 Operating Systems Fall , Lecture 14

Computer Architecture and Assembly Language. Practical Session 5

Assembly Language: IA-32 Instructions

CSC 8400: Computer Systems. Machine-Level Representation of Programs

Abysssec Research. 1) Advisory information. 2) Not vulnerable version

Program Exploitation Intro

Inline Assembler. Willi-Hans Steeb and Yorick Hardy. International School for Scientific Computing

2 Sadeghi, Davi TU Darmstadt 2012 Secure, Trusted, and Trustworthy Computing Chapter 6: Runtime Attacks

Solution to Keygenme 8 by qptˆj

Roadmap: Security in the software lifecycle. Memory corruption vulnerabilities

Lab 3. The Art of Assembly Language (II)

CS24: INTRODUCTION TO COMPUTING SYSTEMS. Spring 2016 Lecture 12

CSCI 334: Principles of Programming Languages. Computer Architecture (a really really fast introduction) Lecture 11: Control Structures II

Buffer Underruns, DEP, ASLR and improving the Exploitation Prevention Mechanisms (XPMs) on the Windows platform

CREA Exam Sample 1605 Malware Analysis Report

CNIT 127: Exploit Development. Ch 3: Shellcode. Updated

Computer Architecture and System Software Lecture 07: Assembly Language Programming

16.317: Microprocessor Systems Design I Fall 2013

Computer Systems Lecture 9

Comparison Of File Infection On The Windows And Linux lclee_vx / F-13 Labs, lychan25/f-13 Labs

Registers. Ray Seyfarth. September 8, Bit Intel Assembly Language c 2011 Ray Seyfarth

LABORATORY WORK NO. 7 FLOW CONTROL INSTRUCTIONS

MWR InfoSecurity Security Advisory. IBM WebSphere MQ - rrilookupget Remote Denial of Service Vulnerability. 4th March 2010

CPS104 Recitation: Assembly Programming

Islamic University Gaza Engineering Faculty Department of Computer Engineering ECOM 2125: Assembly Language LAB. Lab # 10. Advanced Procedures

Assembler Programming. Lecture 10

Function Call Convention

Binghamton University. CS-220 Spring x86 Assembler. Computer Systems: Sections

Using MMX Instructions to Perform Simple Vector Operations

Lecture 15 Intel Manual, Vol. 1, Chapter 3. Fri, Mar 6, Hampden-Sydney College. The x86 Architecture. Robb T. Koether. Overview of the x86

CVE EXPLOIT USING 108 BYTES AND DOWNLOADING A FILE WITH YOUR UNLIMITED CODE BY VALTHEK

Module 3 Instruction Set Architecture (ISA)

Is stack overflow still a problem?

Transcription:

RBS 2015 002 EverFocus Electronics Corp EverNet3 ActiveX Control Multiple Vulnerabilities 2015 07 31 1 of 28

Table of Contents Table of Contents 2 About Risk Based Security 3 Company History 3 Solutions 3 Vulnerable Program Details 4 References 4 Credits 4 Vulnerability Details 5 DestroyOcx() Method Uninitialized Value Use 5 MoveWindow() Method Uninitialized Value Use 7 ProbeDevice() Method Stack Buffer Overflow 8 ReadUnicodeText() Method Stack Buffer Overflow 10 SendHttpRequest() Method Buffer Overflows 11 SendHttpRequest2() Method Heap Buffer Overflow 13 SendHttpRequestEx() Method Buffer Overflows 14 SetRegedit() Method Stack Buffer Overflows 16 SetROIEraser() Method Arbitrary Code Execution 17 SetUnicodeFontInfo() Method Stack Buffer Overflow 20 String Encoding Routine Heap Buffer Overflow 21 RemoveMultiClient() Method Arbitrary Code Execution 24 CreateObjectSizeGrids() Method Stack Buffer Overflow 25 Solution 28 Timeline 28 2015 07 31 2 of 28

About Risk Based Security Risk Based Security offers clients fully integrated security solutions, combining real time vulnerability and threat data, as well as the analytical resources to understand the implications of the data, resulting in not just security, but the right security. Company History Risk Based Security, Inc. (RBS) was established in early 2011 to better support the many users and initiatives of the Open Security Foundation including the OSVDB and DataLossDB projects. RBS was created to transform this wealth of security data into actionable information by enhancing the research available, and providing a first of its kind risk identification and evidence based security management service. As a data driven and vendor neutral organization, RBS is able to deliver focused security solutions that are timely, cost effective, and built to address the specific threats and vulnerabilities most relevant to the organizations we serve. We not only maintain vulnerability and data breach databases, we also use this information to inform our entire practice. Solutions VulnDB Vulnerability intelligence, alerting, and third party library tracking based on the largest and most comprehensive vulnerability database. Available as feature rich SaaS portal or powerful API Cyber Risk Analytics Extensive data breach database including interactive dashboards and breach analytics. Clients are able to gather and analyze security threat and data breach information on businesses, industries, geographies, and causes of loss. YourCISO Revolutionary service that provides organizations an affordable security solution including policies, vulnerability scans, awareness material, incident response, and access to high quality information security resources and consulting services. Vulnerability Assessments (VA) and Pentesting Regularly scheduled VAs and pentests help an organization identify weaknesses before the bad guys do. Managing the most comprehensive VDB puts us in a unique position to offer comprehensive assessments, combining the latest in scanning technology and our own data. Detailed and actionable reports are provided in a clear and easy to understand language. Security Development Lifecycle (SDL) Consulting, auditing, and verification specialized in breaking code, which in turn greatly increases the security of products. 2015 07 31 3 of 28

Vulnerable Program Details Details for tested products and versions: Vendor: EverFocus Electronics Corporation Product: EZN3260 and EDN3340 Version: 1.2.3 130815 Component: EverNet3 ActiveX Control (EverNet3.ocx) Version: 1.0.2.48 NOTE: It is suspected that all IP cameras in the EverFocus EZN and EDN product lines bundle the vulnerable ActiveX control and possibly any products in the NeVio series. Other models and versions than the ones listed above are likely affected. References 1 RBS: RBS 2015 002 OSVDB / VulnDB: 116603, 116604, 116605, 116606, 116607, 116608, 116609, 116610, 116611, 116612, 116613, 116614, 116615, 116616, 116617, 116618, 116619, and 116620 CVE: N/A Credits Carsten Eiram, Risk Based Security Twitter: @CarstenEiram Twitter: @RiskBased 1 https://www.riskbasedsecurity.com/research/rbs 2015 002.pdf 2015 07 31 4 of 28

Vulnerability Details IP cameras in the EverFocus EZN and EDN product lines provide a web based interface for e.g. configuring device settings and streaming footage. When accessed for the first time using Internet Explorer, an ActiveX control, EverNet3.ocx, is installed on the client system. This bundled ActiveX control has been determined to be affected by a large number of critical vulnerabilities, all allowing attackers to compromise the client system when viewing a malicious web page. DestroyOcx() Method Uninitialized Value Use The ActiveX control supports the DestroyOcx() method, which accepts no arguments. When calling the method prior to properly initializing the ActiveX control, the this pointer references an only partially initialized CEverNet3Ctrl object..text:1000b810 M_DestroyOcx proc near ; CODE XREF: CEverNet3Ctrl3::~CEverNet3Ctrl3(void)+4Fp.text:1000B810 ; DATA XREF:.rdata:1007A998o.text:1000B810.text:1000B810 var_20 = dword ptr 20h.text:1000B810 var_1c = dword ptr 1Ch.text:1000B810 lpocevernet3ctrl= dword ptr 18h.text:1000B810 var_14 = dword ptr 14h.text:1000B810 var_10 = dword ptr 10h.text:1000B810 lpocunk1 = dword ptr 0Ch.text:1000B810 lpocunk1_2 = dword ptr 8.text:1000B810 var_4 = dword ptr 4.text:1000B810.text:1000B810 push ebp.text:1000b811 mov ebp, esp.text:1000b813 sub esp, 20h.text:1000B816 mov [ebp+lpocevernet3ctrl], ecx Later in the function, some of these uninitialized values are used to make branching decisions. More importantly, an uninitialized value is eventually treated as an object pointer and dereferenced in a virtual function call. This allows gaining control of the execution flow. 2015 07 31 5 of 28

Figure 1: DestroyOcx() uninitialized value use MoveWindow() Method Uninitialized Value Use The ActiveX control supports the MoveWindow() method, which accepts four arguments: void MoveWindow( long x, long y, long divx, long divy); When calling the method prior to proper initialization of the ActiveX control, the this pointer references an only partially initialized CEverNet3Ctrl object, which is eventually used when 2015 07 31 6 of 28

calling another function..text:100112f0 M_MoveWindow proc near ; DATA XREF:.rdata:1007A758o.text:100112F0.text:100112F0 lpocevernet3ctrl= dword ptr 1Ch.text:100112F0 var_18 = byte ptr 18h.text:100112F0 var_8 = dword ptr 8.text:100112F0 var_4 = dword ptr 4.text:100112F0 arg_0 = dword ptr 8.text:100112F0 arg_4 = dword ptr 0Ch.text:100112F0 arg_8 = dword ptr 10h.text:100112F0 arg_c = dword ptr 14h.text:100112F0.text:100112F0 push ebp.text:100112f1 mov ebp, esp.text:100112f3 sub esp, 1Ch.text:100112F6 mov [ebp+lpocevernet3ctrl], ecx.text:10011407 loc_10011407: ; CODE XREF: M_MoveWindow+F5j.text:10011407 ; M_MoveWindow+106j.text:10011407 mov ecx, [ebp+lpocevernet3ctrl].text:1001140a call sub_1000bf90 Within the called function some of the uninitialized values in memory may be used e.g. as an object pointer dereferenced in a virtual function call. This allows gaining control of the execution flow..text:1000bf90 sub_1000bf90 proc near ; CODE XREF: CEverNet3Ctrl OnSize+3Fp.text:1000BF90 ; M_MoveWindow+11Ap....text:1000BF90.text:1000BF90 lpocevernet3ctrl= dword ptr 8.text:1000BF90 var_4 = dword ptr 4.text:1000BF90.text:1000BF90 push ebp.text:1000bf91 mov ebp, esp.text:1000bf93 sub esp, 8.text:1000BF96 mov [ebp+lpocevernet3ctrl], ecx.text:1000c0bb mov ecx, [eax+edx*4+0b064h] ; uninit mem.text:1000c0c2 mov edx, [ebp+var_4].text:1000c0c5 mov eax, [ebp+lpocevernet3ctrl].text:1000c0c8 mov edx, [eax+edx*4+0b064h].text:1000c0cf mov eax, [ecx].text:1000c0d1 push edx.text:1000c0d2 mov ecx, [eax+0b8h].text:1000c0d8 call ecx 2015 07 31 7 of 28

ProbeDevice() Method Stack Buffer Overflow The ActiveX control supports the ProbeDevice() method, which accepts five arguments: long ProbeDevice( BSTR szid, BSTR szip, BSTR szusr, BSTR szpwd, BSTR szxmlcmd); Before using the szxmlcmd argument, it is passed to a conversion function as source string along with a destination pointer to a 32,772 byte stack buffer..text:10019370 ; int stdcall M_ProbeDevice(int, wchar_t *, wchar_t *, wchar_t *, wchar_t *).text:10019370 M_ProbeDevice proc near ; DATA XREF:.rdata:1007AB58o.text:10019370.text:10019370 pthis = dword ptr 8030h.text:10019370 var_802c = dword ptr 802Ch.text:10019370 ThreadId = dword ptr 8028h.text:10019370 var_8024 = byte ptr 8024h.text:10019370 var_801c = byte ptr 801Ch.text:10019370 var_8018 = byte ptr 8018h.text:10019370 szdstbuf = byte ptr 8014h ; char[32772].text:10019370 var_10 = dword ptr 10h.text:10019370 var_c = dword ptr 0Ch.text:10019370 var_4 = dword ptr 4.text:10019370 arg_0 = dword ptr 8.text:10019370 arg_4 = dword ptr 0Ch.text:10019370 arg_8 = dword ptr 10h.text:10019370 arg_c = dword ptr 14h.text:10019370 pwzxmlcmd = dword ptr 18h.text:1001945D mov eax, [ebp+pwzxmlcmd].text:10019460 push eax ; pwzxmlstr.text:10019461 lea ecx, [ebp+szdstbuf] ; char[32772].text:10019467 push ecx ; pszdstbuf.text:10019468 mov ecx, [ebp+pthis].text:1001946e call ConvertXmlString ; b0f! The conversion function only accepts two arguments: Pointers to source and destination buffers. It calculates the length of the source buffer and uses this as a while loop counter. For each iteration a character is retrieved from the source buffer, converted if required, and written to the destination buffer. 2015 07 31 8 of 28

Figure 2: Overview of conversion function As the conversion function is not supplied the size of the destination buffer to perform bounds checks, it is the responsibility of the calling function to ensure that the destination buffer is properly sized prior to conversion. However, in this case no such checks are performed, leading to a stack based buffer overflow. This allows gaining control of the execution flow. 2015 07 31 9 of 28

ReadUnicodeText() Method Stack Buffer Overflow The ActiveX control supports the ReadUnicodeText() method, which accepts a single argument: long ReadUnicodeText(BSTR strtext); When the method is called, a debug string is created by copying the strtext argument to a 30 wchar stack buffer using _swprintf()..text:100245f0 M_ReadUnicodeText proc near ; DATA XREF:.rdata:1007B2D8o.text:100245F0.text:100245F0 var_2e8 = dword ptr 2E8h.text:100245F0 var_2e4 = dword ptr 2E4h.text:100245F0 var_2e0 = dword ptr 2E0h.text:100245F0 var_2dc = dword ptr 2DCh.text:100245F0 var_2d8 = dword ptr 2D8h.text:100245F0 var_2d4 = dword ptr 2D4h.text:100245F0 var_2d0 = byte ptr 2D0h.text:100245F0 var_2c9 = byte ptr 2C9h.text:100245F0 var_2c8 = dword ptr 2C8h.text:100245F0 var_2c4 = byte ptr 2C4h.text:100245F0 var_2c0 = byte ptr 2C0h.text:100245F0 var_2bc = byte ptr 2BCh.text:100245F0 var_2b8 = dword ptr 2B8h.text:100245F0 MultiByteStr = byte ptr 2B4h.text:100245F0 OutputString = word ptr 254h.text:100245F0 var_54 = byte ptr 54h.text:100245F0 wzdest = word ptr 4Ch ; wchar[30].text:100245f0 var_10 = dword ptr 10h.text:100245F0 var_c = dword ptr 0Ch.text:100245F0 var_4 = dword ptr 4.text:100245F0 pwzstrtext = dword ptr 8.text:10024645 mov eax, [ebp+pwzstrtext].text:10024648 push eax.text:10024649 push offset as_0 ; "%s".text:1002464e lea ecx, [ebp+wzdest] ; wchar[30].text:10024651 push ecx ; Dest.text:10024652 call swprintf ; b0f! As no bounds checks are performed, this allows triggering a stack based buffer overflow and gaining control of the execution flow. 2015 07 31 10 of 28

SendHttpRequest() Method Buffer Overflows The ActiveX control supports the SendHttpRequest() method, which accepts five arguments: long SendHttpRequest( BSTR szid, BSTR szip, BSTR szusr, BSTR szpwd, BSTR szxmlcmd); Prior to being used, the szxmlcmd argument is passed as source string to the conversion function previously described in the ProbeDevice() Method Stack Buffer Overflow section along with a destination pointer to a heap buffer. As no bounds checks are performed prior to calling the function, a heap based buffer overflow may occur..text:100132d0 ; int stdcall M_SendHttpRequest(int, wchar_t *, wchar_t *, wchar_t *, wchar_t *).text:100132d0 M_SendHttpRequest proc near ; DATA XREF:.rdata:1007A958o.text:100132D0....text:100132D0 wzdest = word ptr 22Ch ; wchar[256].text:100132d0 var_2c = dword ptr 2Ch.text:100132D0 var_28 = dword ptr 28h.text:100132D0 var_24 = word ptr 24h.text:100132D0 var_20 = dword ptr 20h.text:100132D0 var_1c = byte ptr 1Ch.text:100132D0 var_10 = dword ptr 10h.text:100132D0 var_c = dword ptr 0Ch.text:100132D0 var_4 = dword ptr 4.text:100132D0 arg_0 = dword ptr 8.text:100132D0 arg_4 = dword ptr 0Ch.text:100132D0 arg_8 = dword ptr 10h.text:100132D0 arg_c = dword ptr 14h.text:100132D0 pwzxmlcmd = dword ptr 18h.text:10013387 mov edx, [ebp+pwzxmlcmd].text:1001338a push edx ; pwzxmlstr.text:1001338b mov eax, [ebp+var_10].text:1001338e add eax, 10h.text:10013391 push eax ; pszdstbuf.text:10013392 mov ecx, [ebp+pthis].text:10013398 call ConvertXmlString ; b0f! 2015 07 31 11 of 28

If a buffer overflow is not triggered within the conversion function, the converted string is eventually passed to another function to craft an HTTP request to /cgi bin/cgistream on a specified IP camera..text:1001341c loc_1001341c: ; CODE XREF: M_SendHttpRequest+E9j.text:1001341C mov ecx, [ebp+poxmlcmd].text:1001341f push ecx.text:10013420 lea ecx, [ebp+var_1c].text:10013423 call SendXmlCmdToCgiStream The called function creates the parameters as part of the request ( video=2&xml=%s ), passing the converted XML command as value to the xml parameter. As the string is written to a 16,388 byte stack buffer using sprintf() without performing any boundary checks, this may lead to a stack based buffer overflow and gaining control of the execution flow..text:10005230 SendXmlCmdToCgiStream proc near ; CODE XREF: M_SendHttpRequest+153p.text:10005230 ; CEverNet3Ctrl vthreadprobe+107p....text:10005230 dwbufferlength = dword ptr 4090h.text:10005230 var_408c = dword ptr 408Ch.text:10005230 Buffer = dword ptr 4088h.text:10005230 dwindex = dword ptr 4084h.text:10005230 dwnumberofbytesread= dword ptr 4080h.text:10005230 wzheaders = word ptr 407Ch ; wchar[50].text:10005230 var_4018 = byte ptr 4018h.text:10005230 szoptional = byte ptr 4014h ; char[16388].text:10005230 var_10 = dword ptr 10h.text:10005230 var_c = dword ptr 0Ch.text:10005230 var_4 = dword ptr 4.text:10005230 poxmlcmd = dword ptr 8.text:10005230.text:10005230 push ebp.text:10005231 mov ebp, esp.text:10005233 push 0FFFFFFFFh.text:10005235 push offset loc_100723cb.text:1000523a mov eax, large fs:0....text:10005292 mov eax, [ebp+poxmlcmd].text:10005295 add eax, 10h.text:10005298 push eax.text:10005299 push offset avideo2xmls ; "video=2&xml=%s".text:1000529e lea ecx, [ebp+szoptional] ; char[16388].text:100052a4 push ecx ; char *.text:100052a5 call _sprintf ; b0f! 2015 07 31 12 of 28

SendHttpRequest2() Method Heap Buffer Overflow The ActiveX control supports the SendHttpRequest2() method, which accepts eight arguments: long SendHttpRequest2( short method, BSTR szip, BSTR szport, BSTR szusr, BSTR szpwd, BSTR szxmlcmd, BSTR szxmlurl, BSTR szfilename); Prior to being used, the szxmlcmd argument is passed as source string to the conversion function previously described in the ProbeDevice() Method Stack Buffer Overflow section along with a destination pointer to a heap buffer. As no bounds checks are performed prior to calling the function, a heap based buffer overflow may occur..text:10019b80 ; int stdcall M_SendHttpRequest2(int, wchar_t *pwzip, wchar_t *pwzport, LPCWSTR pwzusr, LPCWSTR pwzpwd, wchar_t *pwzxmlcmd, wchar_t *pwzxmlurl, wchar_t *pwzfilename).text:10019b80 M_SendHttpRequest2 proc near ; CODE XREF: M_ReadUnicodeText+323p.text:10019B80 ; DATA XREF:.rdata:1007ABD8o....text:10019B80 var_4 = dword ptr 4.text:10019B80 pwzip = dword ptr 0Ch.text:10019B80 pwzport = dword ptr 10h.text:10019B80 pwzusr = dword ptr 14h.text:10019B80 pwzpwd = dword ptr 18h.text:10019B80 pwzxmlcmd = dword ptr 1Ch.text:10019B80 pwzxmlurl = dword ptr 20h.text:10019B80 pwzfilename = dword ptr 24h.text:10019D3A mov eax, [ebp+pwzxmlcmd].text:10019d3d push eax ; pwzxmlstr.text:10019d3e mov ecx, [ebp+pthis].text:10019d41 add ecx, 858h.text:10019D47 push ecx ; pszdstbuf.text:10019d48 mov ecx, [ebp+pthis].text:10019d4b call ConvertXmlString ; b0f! 2015 07 31 13 of 28

SendHttpRequestEx() Method Buffer Overflows The ActiveX control supports the SendHttpRequestEx() method, which accepts 13 arguments: long SendHttpRequestEx( short smethod, short sbehave, BSTR szid, BSTR szip, BSTR szport, short sencode, BSTR szusr, BSTR szpwd, BSTR szxmlheader, BSTR szxmlcmd, BSTR szxmlurl, BSTR szfilename1, BSTR szfilename2); When the method is called, a debug string ( SendHttpRequest: id=%s ip=%s usr=%s pwd=%s xml=%s ) is crafted based on five of the supplied arguments: " szid ", " szip ", " szusr ", " szpwd ", and " szxmlurl "..text:10013580 ; int stdcall M_SendHttpRequestEx( int16 smethod, int16 sbehave, int pwzid, wchar_t *pwzip, wchar_t *pwzport, int16 sencode, LPCWSTR pwzusr, LPCWSTR pwzpwd, wchar_t *pwzxmlheader, wchar_t *pwzxmlcmd, wchar_t *pwzxmlurl, wchar_t *pwzfilename1, wchar_t *pwzfilename2).text:10013580 M_SendHttpRequestEx proc near ; DATA XREF:.rdata:1007B218o.text:10013580....text:10013580 wzdest = word ptr 234h ; wchar[256].text:10013580 var_34 = dword ptr 34h.text:10013580 var_30 = word ptr 30h.text:10013580 var_2c = dword ptr 2Ch.text:10013580 var_28 = byte ptr 28h.text:10013580 var_1c = dword ptr 1Ch.text:10013580 var_18 = byte ptr 18h.text:10013580 var_14 = dword ptr 14h.text:10013580 var_10 = byte ptr 10h.text:10013580 var_c = dword ptr 0Ch.text:10013580 var_4 = dword ptr 4.text:10013580 smethod = word ptr 8.text:10013580 sbehave = word ptr 0Ch.text:10013580 pwzid = dword ptr 10h 2015 07 31 14 of 28

.text:10013580 pwzip = dword ptr 14h.text:10013580 pwzport = dword ptr 18h.text:10013580 sencode = word ptr 1Ch.text:10013580 pwzusr = dword ptr 20h.text:10013580 pwzpwd = dword ptr 24h.text:10013580 pwzxmlheader = dword ptr 28h.text:10013580 pwzxmlcmd = dword ptr 2Ch.text:10013580 pwzxmlurl = dword ptr 30h.text:10013580 pwzfilename1 = dword ptr 34h.text:10013580 pwzfilename2 = dword ptr 38h.text:10013580.text:10013580 push ebp.text:10013581 mov ebp, esp.text:10013583 push 0FFFFFFFFh.text:10013585 push offset loc_10073177.text:1001358a mov eax, large fs:0....text:100135b1 mov eax, [ebp+pwzxmlcmd].text:100135b4 push eax.text:100135b5 mov ecx, [ebp+pwzpwd].text:100135b8 push ecx.text:100135b9 mov edx, [ebp+pwzusr].text:100135bc push edx.text:100135bd mov eax, [ebp+pwzip].text:100135c0 push eax.text:100135c1 mov ecx, [ebp+pwzid].text:100135c4 push ecx.text:100135c5 push offset asendhttpreques ; "SendHttpRequest: id=%s ip=%s usr=%s pwd"....text:100135ca lea edx, [ebp+wzdest] ; wchar[256].text:100135d0 push edx ; Dest.text:100135D1 call swprintf ; b0f! As the string is written into a 256 wchar stack buffer using _swprintf() without performing any boundary checks, this leads to a stack based buffer overflow and allows gaining control of the execution flow. If a buffer overflow is not triggered, the code eventually passes the szxmlurl argument as source string to the conversion function previously described in the ProbeDevice() Method Stack Buffer Overflow section along with a destination pointer to a 8,192 byte heap buffer. As no bounds checks are performed prior to calling the function, a heap based buffer overflow may occur..text:10013664 mov edx, [ebp+pwzxmlurl].text:10013667 push edx ; pwzxmlstr.text:10013668 mov eax, [ebp+var_1c].text:1001366b add eax, 4010h.text:10013670 push eax ; pszdstbuf.text:10013671 mov ecx, [ebp+pthis].text:10013677 call ConvertXmlString ; b0f! 2015 07 31 15 of 28

Similar vulnerable conversion occurs for the szxmlheader and szxmlcmd arguments, also leading to heap based buffer overflows..text:100136a2 push eax ; pwzxmlstr.text:100136a3 mov ecx, [ebp+var_1c].text:100136a6 add ecx, 2010h.text:100136AC push ecx ; pszdstbuf.text:100136ad mov ecx, [ebp+pthis].text:100136b3 call ConvertXmlString ; b0f!.text:100136b8 mov edx, [ebp+pwzxmlcmd].text:100136bb push edx ; pwzxmlstr.text:100136bc mov eax, [ebp+var_1c].text:100136bf add eax, 10h.text:100136C2 push eax ; pszdstbuf.text:100136c3 mov ecx, [ebp+pthis].text:100136c9 call ConvertXmlString ; b0f! SetRegedit() Method Stack Buffer Overflows The ActiveX control supports the SetRegedit() method, which accepts three arguments: short SetRegedit( BSTR szpath, BSTR szname, BSTR szvalue); When called, the responsible function, CEverNet3Ctrl::SetRegedit(), creates the full path for the registry key to set ( Software\Ext\Nevio\%s ) based on the supplied szpath argument..text:10018ae0 ; int stdcall M_SetRegedit(int pwzpath, LPCWSTR pwzvaluename, wchar_t *pwzvalue).text:10018ae0 M_SetRegedit proc near ; DATA XREF:.rdata:1007AAB8o.text:10018AE0.text:10018AE0 var_218 = dword ptr 218h.text:10018AE0 dwdisposition = dword ptr 214h.text:10018AE0 wzdest = word ptr 210h ; wchar[258].text:10018ae0 var_c = dword ptr 0Ch.text:10018AE0 var_8 = dword ptr 8.text:10018AE0 phkresult = dword ptr 4.text:10018AE0 pwzpath = dword ptr 8.text:10018AE0 pwzvaluename = dword ptr 0Ch.text:10018AE0 pwzvalue = dword ptr 10h.text:10018AE0.text:10018AE0 push ebp.text:10018ae1 mov ebp, esp.text:10018ae3 sub esp, 218h 2015 07 31 16 of 28

.text:10018ae9 mov eax, dword_10098c00.text:10018aee xor eax, ebp.text:10018af0 mov [ebp+var_c], eax.text:10018af3 mov [ebp+var_218], ecx.text:10018af9 mov [ebp+phkresult], 0.text:10018B00 push offset acevernet3ctr_4 ; "CEverNet3Ctrl::SetRegedit\n".text:10018B05 call ds:outputdebugstringw.text:10018b0b mov eax, [ebp+pwzpath].text:10018b0e push eax.text:10018b0f push offset asoftwareextn_0 ; "Software\\Ext\\Nevio\\%s".text:10018B14 lea ecx, [ebp+wzdest] ; wchar[258].text:10018b1a push ecx ; Dest.text:10018B1B call swprintf ; b0f! As the path is written into a 258 wchar buffer using _swprintf() without performing any boundary checks, this allows triggering a stack based buffer overflow and gaining control of the execution flow. Later in the function a similar problem exists for the szvalue argument when copied into a 258 wchar stack buffer..text:10018b80 loc_10018b80: ; CODE XREF: M_SetRegedit+74j.text:10018B80 mov edx, [ebp+pwzvalue].text:10018b83 push edx.text:10018b84 push offset as_0 ; "%s".text:10018b89 lea eax, [ebp+wzdest] ; wchar[258].text:10018b8f push eax ; Dest.text:10018B90 call swprintf ; b0f! SetROIEraser() Method Arbitrary Code Execution The ActiveX control supports the SetROIEraser() method, which accepts two arguments: void SetROIEraser( short sch, short sseq); When calling the method prior to properly initializing the ActiveX control, the this pointer references an only partially initialized CEverNet3Ctrl object. This results in uninitialized memory being used in various locations within the function depending on the value of the sseq argument. 2015 07 31 17 of 28

.text:10023020 M_SetROIEraser proc near ; CODE XREF: M_CreateROIMasks+A6p.text:10023020 ; DATA XREF:.rdata:1007B1B8o.text:10023020.text:10023020 lpocevernet3ctrl= dword ptr 20h.text:10023020 var_1c = word ptr 1Ch.text:10023020 var_18 = dword ptr 18h.text:10023020 var_14 = word ptr 14h.text:10023020 var_10 = dword ptr 10h.text:10023020 var_c = dword ptr 0Ch.text:10023020 var_8 = dword ptr 8.text:10023020 lpocunk1 = dword ptr 4.text:10023020 sch = word ptr 8.text:10023020 sseq = word ptr 0Ch.text:10023020.text:10023020 push ebp.text:10023021 mov ebp, esp.text:10023023 sub esp, 20h.text:10023026 mov [ebp+lpocevernet3ctrl], ecx.text:1002308d loc_1002308d: ; CODE XREF: M_SetROIEraser+53j.text:1002308D movsx eax, [ebp+sseq].text:10023091 cmp eax, 63h.text:10023094 jnz loc_1002316c ; sseq!= 99? In cases where sseq is not 99, the code branches to the following location where uninitialized memory is used as an object pointer when calling a virtual function..text:1002316c.text:1002316c loc_1002316c: ; CODE XREF: M_SetROIEraser+74j.text:1002316C movsx edx, [ebp+sseq].text:10023170 shl edx, 2.text:10023173 mov [ebp+var_1c], dx.text:10023177 push offset Data.text:1002317C push 0.text:1002317E push 0.text:10023180 push 0.text:10023182 push 0.text:10023184 push 0.text:10023186 push 0.text:10023188 push 0.text:1002318A push 0.text:1002318C movsx eax, [ebp+sseq].text:10023190 add eax, 0CDh.text:10023195 push eax.text:10023196 mov ecx, [ebp+lpocunk1].text:10023199 mov edx, [ecx] ; read from unit mem.text:1002319b mov eax, [ebp+lpocunk1].text:1002319e push eax.text:1002319f mov ecx, [edx+0f8h].text:100231a5 call ecx 2015 07 31 18 of 28

If sseq is 99, the code branches to the following location where a similar thing happens..text:100230ec mov ecx, [ebp+lpocunk1].text:100230ef mov edx, [ecx] ; read from uninit mem.text:100230f1 mov eax, [ebp+lpocunk1].text:100230f4 push eax.text:100230f5 mov ecx, [edx+0f8h].text:100230fb call ecx Both of these cases allows gaining control of the execution flow. Another problem exists in the function when handling the sch argument, since it s sign extended and used as index into an array without performing any bounds checks. This eventually leads to the referenced memory being treated as an object pointer and stored in a local variable..text:10023020 M_SetROIEraser proc near ; CODE XREF: M_CreateROIMasks+A6p.text:10023020 ; DATA XREF:.rdata:1007B1B8o.text:10023020.text:10023020 lpocevernet3ctrl= dword ptr 20h.text:10023020 var_1c = word ptr 1Ch.text:10023020 var_18 = dword ptr 18h.text:10023020 var_14 = word ptr 14h.text:10023020 var_10 = dword ptr 10h.text:10023020 var_c = dword ptr 0Ch.text:10023020 var_8 = dword ptr 8.text:10023020 lpocunk1 = dword ptr 4.text:10023020 sch = word ptr 8.text:10023020 sseq = word ptr 0Ch.text:10023020.text:10023020 push ebp.text:10023021 mov ebp, esp.text:10023023 sub esp, 20h.text:10023026 mov [ebp+lpocevernet3ctrl], ecx.text:10023035 movsx ecx, [ebp+sch].text:10023039 mov edx, [ebp+lpocevernet3ctrl].text:1002303c cmp dword ptr [edx+ecx*4+0b074h], 0.text:10023044 jnz short loc_1002304b ; value!= 0?.text:1002304B.text:1002304B loc_1002304b: ; CODE XREF: M_SetROIEraser+24j.text:1002304B movsx eax, [ebp+sch].text:1002304f mov ecx, [ebp+lpocevernet3ctrl].text:10023052 mov edx, [ecx+eax*4+0b064h] ; use as index into array.text:10023059 mov [ebp+lpocunk1], edx ; store as object pointer 2015 07 31 19 of 28

Depending on the value of the sseq argument, as mentioned in the previous section, one of two code locations may eventually dereference the value when calling a virtual function..text:10023196 mov ecx, [ebp+lpocunk1].text:10023199 mov edx, [ecx].text:1002319b mov eax, [ebp+lpocunk1].text:1002319e push eax.text:1002319f mov ecx, [edx+0f8h].text:100231a5 call ecx And.text:100230EC mov ecx, [ebp+lpocunk1].text:100230ef mov edx, [ecx].text:100230f1 mov eax, [ebp+lpocunk1].text:100230f4 push eax.text:100230f5 mov ecx, [edx+0f8h].text:100230fb call ecx This allows gaining control of the execution flow. SetUnicodeFontInfo() Method Stack Buffer Overflow The ActiveX control supports the SetUnicodeFontInfo() method, which accepts four arguments: long SetUnicodeFontInfo( short sfonth, short sisshift, long lfontweight, BSTR strfonttype); When the method is called, the strfonttype argument is copied into a 30 wchar stack buffer using _swprintf() without performing any boundary checks..text:10024500 M_SetUnicodeFontInfo proc near ; DATA XREF:.rdata:1007B2F8o.text:10024500.text:10024500 wzdest = word ptr 50h ; wchar[30].text:10024500 var_14 = dword ptr 14h.text:10024500 var_10 = word ptr 10h.text:10024500 var_c = dword ptr 0Ch.text:10024500 var_4 = dword ptr 4.text:10024500 sfonth = word ptr 8.text:10024500 sisshift = word ptr 0Ch.text:10024500 lfontweight = dword ptr 10h.text:10024500 pstrfonttype = dword ptr 14h 2015 07 31 20 of 28

.text:10024500.text:10024500 push ebp.text:10024501 mov ebp, esp.text:10024503 push 0FFFFFFFFh.text:10024505 push offset loc_10073fa8.text:1002450a mov eax, large fs:0.text:1002457f mov edx, [ebp+pstrfonttype].text:10024582 push edx.text:10024583 push offset as_0 ; "%s".text:10024588 lea eax, [ebp+wzdest] ; wchar[30].text:1002458b push eax ; Dest.text:1002458C call swprintf ; b0f! This leads to a stack based buffer overflow and allows gaining control of the execution flow. String Encoding Routine Heap Buffer Overflow The ActiveX control supports the SimpleEncDecStr() method, which accepts two arguments: BSTR SimpleEncDecStr( short method, BSTR strname); When the SimpleEncDecStr() method is called, the string supplied via the strname argument is converted using WideCharToMultiByte() into a 128 byte destination buffer..text:1001a800 ; int stdcall M_SimpleEncDecStr( int16 smethod, LPCWSTR pwzstrname).text:1001a800 M_SimpleEncDecStr proc near ; CODE XREF: M_Play+752p.text:1001A800 ; M_Play+783p.......text:1001A800 punk1 = dword ptr 98h.text:1001A800 szmultibytestr = byte ptr 94h ; char[128].text:1001a800 var_14 = dword ptr 14h.text:1001A800 lpocstringdata = byte ptr 10h.text:1001A800 var_c = dword ptr 0Ch.text:1001A800 iunkzero = dword ptr 4.text:1001A800 smethod = word ptr 8.text:1001A800 pwzstrname = dword ptr 0Ch.text:1001A800.text:1001A800 push ebp.text:1001a801 mov ebp, esp.text:1001a803 push 0FFFFFFFFh.text:1001A805 push offset loc_1007362e.text:1001a80a mov eax, large fs:0....text:1001a831 push 80h ; size_t 2015 07 31 21 of 28

.text:1001a836 push 0 ; int.text:1001a838 lea eax, [ebp+szmultibytestr] ; char[128].text:1001a83e push eax ; void *.text:1001a83f call _memset.text:1001a844 add esp, 0Ch.text:1001A847 push 0 ; lpuseddefaultchar.text:1001a849 push 0 ; lpdefaultchar.text:1001a84b push 80h ; cbmultibyte.text:1001a850 lea ecx, [ebp+szmultibytestr] ; char[128].text:1001a856 push ecx ; lpmultibytestr.text:1001a857 push 0FFFFFFFFh ; cchwidechar.text:1001a859 mov edx, [ebp+pwzstrname].text:1001a85c push edx ; lpwidecharstr.text:1001a85d push 0 ; dwflags.text:1001a85f push 0 ; CodePage.text:1001A861 call ds:widechartomultibyte Checks then confirm that the value passed via the method argument is either 0 or 1. This defines whether the function should decode (0) or encode (1) the supplied string. In case the value is 1, the function calls SimpleEecStr() to encode the string..text:1001a876 movsx eax, [ebp+smethod].text:1001a87a test eax, eax.text:1001a87c jnz short loc_1001a8ca ; method!= 0?.text:1001A8CA loc_1001a8ca: ; CODE XREF: M_SimpleEncDecStr+7Cj.text:1001A8CA movsx edx, [ebp+smethod].text:1001a8ce cmp edx, 1.text:1001A8D1 jnz short @exit ; method!= 1?.text:1001A8D3 lea eax, [ebp+szmultibytestr] ; char[128].text:1001a8d9 push eax ; pszstring.text:1001a8da lea ecx, [ebp+var_9c].text:1001a8e0 push ecx ; punk1.text:1001a8e1 call SimpleEecStr Inside SimpleEecStr() the length of the string is calculated using strlen(). Memory is then allocated based on the length * 4 + 2. This is to ensure sufficient room for each byte being encoded into 4 bytes along with the NULL terminator..text:10010410 ; int cdecl SimpleEecStr(int punk1, char *pszstring).text:10010410 SimpleEecStr proc near ; CODE XREF: M_SimpleEncDecStr+E1p.text:10010410.text:10010410 var_48 = dword ptr 48h.text:10010410 icount = dword ptr 44h.text:10010410 wzdest = word ptr 40h ; wchar[16].text:10010410 var_20 = dword ptr 20h.text:10010410 lpoutputstring = dword ptr 1Ch.text:10010410 uistringlength = dword ptr 18h.text:10010410 uistringlengthx2= dword ptr 14h.text:10010410 var_10 = byte ptr 10h.text:10010410 var_c = dword ptr 0Ch.text:10010410 var_4 = dword ptr 4.text:10010410 punk1 = dword ptr 8.text:10010410 pszstring = dword ptr 0Ch 2015 07 31 22 of 28

.text:10010410.text:10010410 push ebp.text:10010411 mov ebp, esp.text:10010413 push 0FFFFFFFFh.text:10010415 push offset loc_10072e78.text:1001041a mov eax, large fs:0....text:10010453 mov eax, [ebp+pszstring].text:10010456 push eax ; char *.text:10010457 call _strlen ; doesn't account for missing NULL termination.text:1001045c add esp, 4.text:1001045F mov [ebp+uistringlength], eax.text:10010462 mov ecx, [ebp+uistringlength].text:10010465 shl ecx, 1.text:10010467 mov [ebp+uistringlengthx2], ecx.text:1001046a mov edx, [ebp+uistringlengthx2].text:1001046d lea eax, [edx+edx+2].text:10010471 push eax ; size_t.text:10010472 call _malloc ; allocation assumes 1 byte = 4 bytes encoded + NULL terminator.text:10010477 add esp, 4.text:1001047A mov [ebp+lpoutputstring], eax The encoding routine is then entered. The string is encoded one byte at a time and the result appended to the previously allocated output buffer. The first step of the encoding process changes the value of the current byte based on its position in the string. This resulting byte value is then sign extended and passed to swprintf() using the " %.2X " format specifier before being written to the output buffer using wcscat(). 2015 07 31 23 of 28

Figure 3: Encoding loop The developer seemingly expected the precision specifier to limit the output to two wide characters, but precision used with the 'X' specifier specifies the minimum number of digits. As the encoded byte value is sign extended, the result of calling swprintf() with the " %.2X " format specifier may be a 16 byte string. As the heap based buffer was allocated on the assumption that a byte is encoded to 4 bytes, a heap based buffer overflow can be triggered. RemoveMultiClient() Method Arbitrary Code Execution The ActiveX control supports the RemoveMultiClient() method, which accepts a single argument: void RemoveMultiClient(short schannel); Two problems exist in the CEverNet2Ctrl::RemoveMultiClient() function handling calls to this method. Firstly, the supplied schannel argument is sign extended and used as an index into an array in the CEverNet2Ctrl object to retrieve an object pointer without performing any bounds checks. Secondly, when calling the method without properly initializing the control, the mentioned array contains uninitialized values that are treated as object pointers and dereferenced when performing a virtual function call..text:1001d760 M_RemoveMultiClient proc near ; CODE XREF: M_AddMultiClient+9Bp.text:1001D760 ; M_AddMultiClient+29Dp....text:1001D760.text:1001D760 lpthis = dword ptr 4.text:1001D760 schannel = word ptr 8.text:1001D760.text:1001D760 push ebp.text:1001d761 mov ebp, esp.text:1001d763 push ecx.text:1001d764 mov [ebp+lpthis], ecx.text:1001d767 movsx eax, [ebp+schannel].text:1001d76b mov ecx, [ebp+lpthis].text:1001d76e mov edx, [ecx+eax*4+0b064h] ; uninit mem / OOB read.text:1001d775 movsx eax, [ebp+schannel].text:1001d779 mov ecx, [ebp+lpthis].text:1001d77c mov eax, [ecx+eax*4+0b064h].text:1001d783 mov ecx, [edx].text:1001d785 push eax.text:1001d786 mov edx, [ecx+0a0h].text:1001d78c call edx Both cases allow gaining control of the execution flow. 2015 07 31 24 of 28

These issues are also triggerable via the CEverNet2Ctrl::AddFilledClient() function handling calls to the AddFilledClient() method as well as the CEverNet2Ctrl::AddMultiClient() function handling calls to the AddMultiClient() method. In both cases, the methods also accept a schannel argument eventually passed to the CEverNet2Ctrl::RemoveMultiClient() function. short AddFilledClient( short schannel, BSTR szsource, BSTR szencusr, BSTR szencpwd); short AddMultiClient( short schannel, BSTR szsource, BSTR szencusr, BSTR szencpwd); CreateObjectSizeGrids() Method Stack Buffer Overflow The ActiveX control supports the CreateObjectSizeGrids() method, which accepts five arguments: short CreateObjectSizeGrids( short sch, short senable, short swnum, short shnum, BSTR lpselgrid); When the method is called, a debug string is crafted based on the supplied arguments..text:100238c0 ; int stdcall M_CreateObjectSizeGrids( int16, int16, int16, int16, wchar_t *).text:100238c0 M_CreateObjectSizeGrids proc near ; DATA XREF:.rdata:1007B298o.text:100238C0.text:100238C0 wzdest = word ptr 21Ch ; wchar[258].text:100238c0 var_18 = dword ptr 18h.text:100238C0 var_14 = byte ptr 14h.text:100238C0 var_c = dword ptr 0Ch 2015 07 31 25 of 28

.text:100238c0 var_4 = dword ptr 4.text:100238C0 arg_0 = word ptr 8.text:100238C0 arg_4 = word ptr 0Ch.text:100238C0 arg_8 = word ptr 10h.text:100238C0 arg_c = word ptr 14h.text:100238C0 arg_10 = dword ptr 18h.text:100238C0.text:100238C0 push ebp.text:100238c1 mov ebp, esp....text:1002390b mov eax, [ebp+arg_10].text:1002390e push eax.text:1002390f movsx ecx, [ebp+arg_c].text:10023913 push ecx.text:10023914 movsx edx, [ebp+arg_8].text:10023918 push edx.text:10023919 movsx eax, [ebp+arg_4].text:1002391d push eax.text:1002391e movsx ecx, [ebp+arg_0].text:10023922 push ecx.text:10023923 push offset adddds ; "%d, %d, %d, %d, %s \n".text:10023928 lea edx, [ebp+wzdest] ; wchar[258].text:1002392e push edx ; Dest.text:1002392F call swprintf ; b0f! As the string is written into a 258 wchar stack buffer using _swprintf() without performing any boundary checks, it s possible to trigger a stack based buffer overflow and gain control of the execution flow. CreateAreaLine() Method Uninitialized Value Use Arbitrary Code Execution The ActiveX control supports the CreateAreaLine() method, which accepts six arguments: short CreateAreaLine( short sch, short senable, short scolor, short spenbold, short swnum, short shnum); When calling the method prior to properly initializing the ActiveX control, the this pointer references an only partially initialized CEverNet3Ctrl object. Eventually, the code checks the value of the supplied sch argument..text:1001f620 M_CreateAreaLine proc near.text:1001f620.text:1001f620 lpthis = dword ptr 8 ; DATA XREF:.rdata:1007B098o 2015 07 31 26 of 28

.text:1001f620 icount = dword ptr 4.text:1001F620 sch = word ptr 8.text:1001F620 senable = word ptr 0Ch.text:1001F620 scolor = word ptr 10h.text:1001F620 spenbold = word ptr 14h.text:1001F620 swnum = word ptr 18h.text:1001F620 shnum = word ptr 1Ch.text:1001F620.text:1001F620 push ebp.text:1001f621 mov ebp, esp.text:1001f623 sub esp, 8.text:1001F626 mov [ebp+lpthis], ecx....text:1001f655 movsx edx, [ebp+sch].text:1001f659 cmp edx, 63h.text:1001F65C jnz short loc_1001f6bf ; sch!= 99? If not set to 99, two additional checks ensure that the sign extended result is neither negative nor 4 or greater..text:1001f6bf loc_1001f6bf: ; CODE XREF: M_CreateAreaLine+3Cj.text:1001F6BF movsx eax, [ebp+sch].text:1001f6c3 test eax, eax.text:1001f6c5 jl short loc_1001f710 ; negative?.text:1001f6c7 movsx ecx, [ebp+sch].text:1001f6cb cmp ecx, 4.text:1001F6CE jge short loc_1001f710 ; sch >= 4? If passing the check, the sch argument is used as index into an array inside the CEverNet3Ctrl object. However, the values in this array may be uninitialized, resulting in one of these being treated as an object pointer and dereferenced when calling a virtual function. This allows gaining control of the execution flow..text:1001f6d0 mov dx, [ebp+shnum].text:1001f6d4 push edx.text:1001f6d5 mov ax, [ebp+swnum].text:1001f6d9 push eax.text:1001f6da mov cx, [ebp+spenbold].text:1001f6de push ecx.text:1001f6df mov dx, [ebp+scolor].text:1001f6e3 push edx.text:1001f6e4 mov ax, [ebp+senable].text:1001f6e8 push eax.text:1001f6e9 movsx ecx, [ebp+sch].text:1001f6ed mov edx, [ebp+lpthis].text:1001f6f0 mov eax, [edx+ecx*4+0b064h] ; uninit mem.text:1001f6f7 movsx ecx, [ebp+sch].text:1001f6fb mov edx, [ebp+lpthis].text:1001f6fe mov ecx, [edx+ecx*4+0b064h].text:1001f705 mov edx, [eax].text:1001f707 push ecx.text:1001f708 mov eax, [edx+0f4h].text:1001f70e call eax 2015 07 31 27 of 28

If the sch argument was set to 99, another similar dereference of an uninitialized value occurs..text:1001f67d mov cx, [ebp+shnum].text:1001f681 push ecx.text:1001f682 mov dx, [ebp+swnum].text:1001f686 push edx.text:1001f687 mov ax, [ebp+spenbold].text:1001f68b push eax.text:1001f68c mov cx, [ebp+scolor].text:1001f690 push ecx.text:1001f691 mov dx, [ebp+senable].text:1001f695 push edx.text:1001f696 mov eax, [ebp+icount].text:1001f699 mov ecx, [ebp+lpthis].text:1001f69c mov edx, [ecx+eax*4+0b064h].text:1001f6a3 mov eax, [ebp+icount].text:1001f6a6 mov ecx, [ebp+lpthis].text:1001f6a9 mov eax, [ecx+eax*4+0b064h].text:1001f6b0 mov ecx, [edx].text:1001f6b2 push eax.text:1001f6b3 mov edx, [ecx+0f4h].text:1001f6b9 call edx Solution The vendor was not responsive, and we are not aware of any available fix for these vulnerabilities. Timeline 2014 10 23 Vulnerabilities discovered. 2014 12 08 Emailed vendor to obtain details for security contact. 2015 01 01 2 OSVDB entries published and details made available on VulnDB. 2015 07 31 Publication of this vulnerability report. 2 https://www.riskbasedsecurity.com/risk data analytics/vulnerability database/ 2015 07 31 28 of 28