2016-09-04 12 views
4

C++でC#Random()クラスを実装する方法はありますか?私は具体的には、与えられた種に基づいて同じ数列を生成する必要があります。C#でC#Random()をエミュレートする(同じ番号)

シナリオ: 私はいくつかの暗号化マルウェアをC#のRandom()の使用法を悪用して暗号化し、鍵を生成しています。明らかに、これはわずか2^32の可能なキー、〜4.3Bのキーしか持たないことに弱いです。これは推測の可能性の領域です。私はC#でbruteforcerを書いていますが、どれくらい最適化しても、どちらも遅いです。私は解読部でより良い速度の最適化を得ることができるので、最高の効率(ハードウェアに近い)のためにC++でbruteforcerを実装したいと考えています(例えばAES-256は一般的に将来GPUを活用することさえできます)指数関数的に優れた出力を得ることができます。

もちろん、異なるジェネレータに基づいてランダム(seed)!= srand(seed)です。 PRNG C#をC++で実装する方法はありますか?私は明らかに暗号化が被害者のファイルに施されているので、C#マルウェアを修正することはできませんので、単に同じ共通のRNGを使用するように両方を書き直すことはできません。

+1

C++標準では、C#が行う擬似乱数ジェネレータに同じ式を指定することはほとんどありません。 C#の疑似RNGの仕様を調査して特定し、C++で再実装する必要があります。 –

+1

"C++でPRNG C#を実装する方法はありますか?" "XはYでできます。私はZでもXもできますか?"などの質問に対する答えは_常に_はいです。 C#は何もできない魔法のC++はできません。 – Cubic

+1

実際には2^31の可能なキーですが、コンストラクタで['Math.Abs​​(seed)'を呼び出す](http://referencesource.microsoft.com/#mscorlib/system/random.cs,62)負の数値は正の数値に変換されます。 –

答えて

5

ランダム(C#の場合)のソースはhereです。

+0

ソースがオープンソースであることを忘れてしまいました。 VisualStudioはそれには役に立たなかったので、私はオンライン文書をチェックしないという間違いを犯しました。 >。<私はちょうどC++でアルゴリズムを再実装し、そこから行くつもりです。 :) – Demonslay335

+1

助けてくれてうれしいです。ソースが無料であることを忘れるのは簡単です。あなたの再実装で幸運。 – js441

3

回答とコメントはありがとうございます。他の誰かが同様のプロジェクトを必要としている場合は、移植したC++コードをここに投稿しています。それはかなりコピー/貼り付けであり、数行を「翻訳」して適切なプロトタイプに分解しなければなりませんでした。 C#アプリケーションとまったく同じシーケンスをサイドバイサイドに確認します。 :)

Random.h

#include <limits> 

#pragma once 
class Random 
{ 
private: 
    const int MBIG = INT_MAX; 
    const int MSEED = 161803398; 
    const int MZ = 0; 

    int inext; 
    int inextp; 
    int *SeedArray = new int[56](); 

    double Sample(); 
    double GetSampleForLargeRange(); 
    int InternalSample(); 

public: 
    Random(int seed); 
    ~Random(); 
    int Next(); 
    int Next(int minValue, int maxValue); 
    int Next(int maxValue); 
    double NextDouble(); 
}; 

Random.cpp

#include "stdafx.h" 
#include "Random.h" 
#include <limits.h> 
#include <math.h> 
#include <stdexcept> 

double Random::Sample() { 
    //Including this division at the end gives us significantly improved 
    //random number distribution. 
    return (this->InternalSample()*(1.0/MBIG)); 
} 

int Random::InternalSample() { 
    int retVal; 
    int locINext = this->inext; 
    int locINextp = this->inextp; 

    if (++locINext >= 56) locINext = 1; 
    if (++locINextp >= 56) locINextp = 1; 

    retVal = SeedArray[locINext] - SeedArray[locINextp]; 

    if (retVal == MBIG) retVal--; 
    if (retVal<0) retVal += MBIG; 

    SeedArray[locINext] = retVal; 

    inext = locINext; 
    inextp = locINextp; 

    return retVal; 
} 

Random::Random(int seed) { 
    int ii; 
    int mj, mk; 

    //Initialize our Seed array. 
    //This algorithm comes from Numerical Recipes in C (2nd Ed.) 
    int subtraction = (seed == INT_MAX) ? INT_MAX : abs(seed); 
    mj = MSEED - subtraction; 
    SeedArray[55] = mj; 
    mk = 1; 
    for (int i = 1; i<55; i++) { //Apparently the range [1..55] is special (Knuth) and so we're wasting the 0'th position. 
     ii = (21 * i) % 55; 
     SeedArray[ii] = mk; 
     mk = mj - mk; 
     if (mk<0) mk += MBIG; 
     mj = SeedArray[ii]; 
    } 
    for (int k = 1; k<5; k++) { 
     for (int i = 1; i<56; i++) { 
      SeedArray[i] -= SeedArray[1 + (i + 30) % 55]; 
      if (SeedArray[i]<0) SeedArray[i] += MBIG; 
     } 
    } 
    inext = 0; 
    inextp = 21; 
    seed = 1; 
} 

Random::~Random() 
{ 
    delete SeedArray; 
} 

int Random::Next() { 
    return this->InternalSample(); 
} 

double Random::GetSampleForLargeRange() { 

    int result = this->InternalSample(); 
    // Note we can't use addition here. The distribution will be bad if we do that. 
    bool negative = (InternalSample() % 2 == 0) ? true : false; // decide the sign based on second sample 
    if (negative) { 
     result = -result; 
    } 
    double d = result; 
    d += (INT_MAX - 1); // get a number in range [0 .. 2 * Int32MaxValue - 1) 
    d /= 2 * INT_MAX - 1; 
    return d; 
} 

int Random::Next(int minValue, int maxValue) { 
    if (minValue>maxValue) { 
     throw std::invalid_argument("minValue is larger than maxValue"); 
    } 

    long range = (long)maxValue - minValue; 
    if (range <= (long)INT_MAX) { 
     return ((int)(this->Sample() * range) + minValue); 
    } 
    else { 
     return (int)((long)(this->GetSampleForLargeRange() * range) + minValue); 
    } 
} 


int Random::Next(int maxValue) { 
    if (maxValue<0) { 
     throw std::invalid_argument("maxValue must be positive"); 
    } 

    return (int)(this->Sample()*maxValue); 
} 

double Random::NextDouble() { 
    return this->Sample(); 
} 

MAIN.CPP

#include "Random.h" 
#include <iostream> 

int main(int argc, char* argv[]){ 
    // Example usage with a given seed 
    Random r = Random(7898); 
    std::cout << r.Next() << std::endl; 
}