ida安裝包密碼算法

我的環境:mac,perl v5.18.4並不是5.20是可以跑出7.2和6.8的,但是7.0和其他的不行。

#!/usr/bin/env perl
#
@_e = split //,"abcdefghijkmpqrstuvwxyzABCDEFGHJKLMPQRSTUVWXYZ23456789";
 
$i=$ARGV[0];
srand($i);
$pw="";

 
for($i=0;$i<12;++$i)
{
        $key = rand 54;
        $pw = $pw . $_e[$key];
}
# print "$i $pw\n";
if($pw eq "7JpT48a7Y2fv"){
	print "$i $pw\n";
	exit 1;
}

因爲經測試,像https://bbs.pediy.com/thread-252145.htm中寫是不行的,循環內執行srand重新設置種子和第一個設置種子的產生的隨機數不同,也就是第一次是正確的,之後再設置srand就不行了。

#!/usr/bin/env perl
#
@_e = split //,"abcdefghijkmpqrstuvwxyzABCDEFGHJKLMPQRSTUVWXYZ23456789";
 
for($ii=0;$ii<4294967295;++$ii){
    srand($ii);
    $pw="";
 
    for($i=0;$i<12;++$i)
    {
        $key = rand 54;
        $pw = $pw . $_e[$key];
    }
    print "$pw\n";
}

所以寫了個shell腳本來跑,但是效率實在是太慢了。。。

#!/bin/bash

for((i=0;i<=0xffffffff;i++));
do
	md="perl /Users/ong/Downloads/tida/my.perl $i"
	# echo $md
	re=$($md)
	# echo $re
	ret=$(echo $?)
	# echo $ret
	if [[ $ret == 1 ]]; then
		#statements
		echo "found $re $i"
	fi
done

計算一下一秒32次,生成完字典。。。而這個其實確實可以跑出7.2的,可以試下$i=948301080;循環之前先rand;一次。

聽說是用的drand48,寫個c++項目使用drand48,和prel並不一致。找了個據說是FreeBSD's drand48的代碼

#define m 0x100000000LL
#define c 0xB16
#define a 0x5DEECE66DLL

static unsigned long long seed = 1;

double drand48(void)
{
    seed = (a * seed + c) & 0xFFFFFFFFFFFFLL;
    unsigned int x = seed >> 16;
    return  ((double)x / (double)m);

}

void srand48(unsigned int i)
{
    seed  = (((long long int)i) << 16) | rand();
}

還是和perl的不一致。

看到https://github.com/seritools/find_drand48_innosetup_pw/blob/master/src/rand48.rs

use float_extras::f64::ldexp;

/// Double Rand48 64bit impl based on perl's PRNG implementation
pub struct DRand48 {
    pub x: u64
}

impl DRand48 {
    #[inline]
    pub fn next_f64(&mut self) -> f64 {
        let x = (self.x.wrapping_mul(0x5DEE_CE66D).wrapping_add(0xB)) & 0xFFFF_FFFF_FFFF;
        self.x = x;
        ldexp(x as f64, -48)
    }

    #[inline]
    pub fn set_seed(&mut self, seed: u32) {
        const FREEBSD_DRAND48_SEED_0: u64 = 0x330e;
        self.x = FREEBSD_DRAND48_SEED_0 + (u64::from(seed) << 16);
    }
}

 

mod rand48;
use rand48::DRand48;

use hex_literal::hex;
use rayon::iter::*;
use sha1::{Digest, Sha1};

const CHARS: &[u8; 54] = b"abcdefghijkmpqrstuvwxyzABCDEFGHJKLMPQRSTUVWXYZ23456789";

const SALT1: &[u8; 17] = b"PasswordCheckHash";

// change these to the actual values you want to find for
const SALT2: [u8; 8] = hex!("0000000000000000");
const HASH: [u8; 20] = hex!("0000000000000000000000000000000000000000");

fn main() {
    let sha1template = {
        let mut hasher = Sha1::new();
        hasher.input(SALT1);
        hasher.input(SALT2);
        hasher
    };

    let result = (0u32..=0xFF)
        .into_par_iter()
        .filter_map(|n| {
            let pos: u32 = n << 24;
            println!(
                "Checking block {}/256 (seeds {:X}-{:X})",
                n + 1,
                pos,
                (pos + 0xFF_FFFF)
            );

            let mut buf = [0u16; 12];
            let mut rand = DRand48 { x: 0 };
            for i in pos..(pos + 0xFF_FFFF) {
                rand.set_seed(i);

                // skip first value
                rand.next_f64();

                let mut n = 0;
                while n < 12 {
                    n += (CHARS[(rand.next_f64() * 54.0) as usize] as char)
                        .encode_utf16(&mut buf[n..])
                        .len();
                }

                let hash = {
                    let mut hasher = sha1template.clone();
                    hasher.input(unsafe {
                        std::slice::from_raw_parts(
                            (buf[..]).as_ptr() as *const _,
                            buf[..].len() * 2,
                        )
                    });
                    hasher.result()
                };

                if hash[..] == HASH {
                    return Some(buf);
                }
            }
            None
        })
        .find_any(|_| true);

    if let Some(buf) = result {
        println!("FOUND: {}", String::from_utf16(&buf[..]).unwrap());
    }
}

好像是ruby的代碼,不懂ruby,靠猜和驗證,寫了出來,和perl的一致,所以這樣每次重新給seed賦值,應該可以不用shell了。

#define m 0x100000000LL
//#define c 0xB16
#define c 0xB
#define a 0x5DEECE66DLL

static unsigned long long seed = 1;

double drand48(void)
{
    seed = (a * seed + c) & 0xFFFFFFFFFFFFLL;
    unsigned int x = seed >> 16;
    return  ((double)x / (double)m);

}

void set_seed() {
    const unsigned long long FREEBSD_DRAND48_SEED_0 = 0x330e;
    seed = FREEBSD_DRAND48_SEED_0 + ((seed) << 16);
}

int main(int argc, char* argv[])
{

    seed = 948301080;
    set_seed();

    string pw;
    char *table = "abcdefghijkmpqrstuvwxyzABCDEFGHJKLMPQRSTUVWXYZ23456789";

    for(int i=0;i<12;++i)
    {
        double tmp = drand48();

        int key = tmp * 54;
        //printf("%d\n", key);
        pw = pw + table[key];
    }

    std::cout << pw << std::endl;
}

但是7.0和其他的不知道怎麼辦,說是低於perl5.20,我這是低於的,我也不想再寫其他版本測試。

根據文章所說,"Old" is Microsoft's LCG rand(),找了lcg的算法,但是對不上

$seed=3326487116;
sub myrand{
	$seed=(214013*$seed+2531011)&0x7fffffff;
	# $seed=(214013*$seed+2531011)%2147483648;
	print "$seed \n";
	$tp=$seed>>16;
	$seed=$tp;
	print "$tp \n";
	return($tp);
}

//參考的
unsigned int Rando::LCG()
{
  x_[1] = x_[0];
  x_[0] = (x_[1]*214013 + 2531011)&((1U << 31) - 1) >> 16;
  return x_[0];
}

unsigned int Rando::microsoftRand()
{
  x_[1] = x_[0];
  x_[0] = (x_[1] * 214013 + 2531011) % 2147483648;
  return (x_[0] >> 16);
}

使用c++調用rand之類的肯定也是不行的,而且https://devco.re/blog/2019/06/21/operation-crack-hacking-IDA-Pro-installer-PRNG-from-an-unusual-way-en/https://www.reddit.com/r/ReverseEngineering/comments/c3myjd/operation_crack_hacking_ida_pro_installer_prng/中的

"password";     // IDA ver // gen // seed[, seed]       // notes
"7JpT48a7Y2fv";	// IDA 7.2 // New // 3885ED18           // drand48(), 13 calls, discard first result, use following 12; PasswordHash = f29f55f07c043ad34b3de150501535f44424edad PasswordSalt = c41639792846e456; UTF16LE password (hashcat -m 140)
"qY2jts9hEJGy";	// IDA 7.0 // Old // 3AC5C29B, BAC5C29B
"ZFdLqEM2QMVe";	// IDA 6.8 // Old // 2FF0126C, AFF0126C
"PDxD5J82DsFy";	// IDA 6.8 // New // 842411E7
"FgVQyXZY2XFk";	// IDA 6.8 // New // C6462A4C
"DuTLLYLCj3dU";	// IDA 6.7 // Old // 672B02C6, E72B02C6 // PasswordHash = 137afe87e9104665bd38a95ca3954e8d7eb6d12a PasswordSalt = aae8123520fa8013 
"itJpyHidszaR";	// IDA 6.6 // Old // 25681E67, A5681E67
"7ChFzSbF4aik";	// IDA 6.5 // Old // 626D5BFE, E26D5BFE
"6VYGSyLguBfi";	// IDA 6.3 // Old // 73171059, F3171059
"TuLWLErJwMHx";	// IDA 6.2 // New // CFD6740C
"6A8RYbHhHrH";	// IDA 5.2 // Old // 1ADD7BD6, 9ADD7BD6
"eyKiZ5dXXzd";	// Hex 5.2 // Old // 6253A857, E253A857

標爲old的有兩個seed?搞不懂了。

按照這個

use libc::{rand, srand};

#[inline]
fn perl_srand(seed: u32) {
unsafe { srand(seed) }
}

#[inline]
fn perl_rand(max: u32) -> usize {
(f64::from(unsafe { rand() } & 0x7FFF) / ((1u64 << 15) as f64) * f64::from(max)) as usize
}

寫成c++,結果也不對。

int perl_rand(unsigned int max) {
    long long r = rand();
    r &= 0x7FFF;

    double tmp = (double)r / (double)(1 << 15);
    cout << r << "=" << tmp << endl;

    return tmp * max;
}

放棄了,不想去翻perl源碼了。還看到https://hastebin.com/uxeqiqofim.cpp這個的代碼,我很懷疑能不能跑出7.2,可能6.8都跑不出吧?結果居然drand48和perl一致,呃,原來我使用的srand而不是srand48初始化種子造成的?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>

// $ innoextract --show-password IDA-Pro-v7.2.exe
// Inspecting "IDA Pro v7.2 and Hex-Rays Decompiler (x64)" - setup data version 5.5.7 (unicode)
// Password hash: SHA-1 f29f55f07c043ad34b3de150501535f44424edad
// Password salt: 50617373776f7264436865636b48617368c41639792846e456 (hex bytes, prepended to password)
// Password encoding: UTF-16LE
// hashcat -m 140 sha1($salt.utf64le($pass))
// gcc -I"${PREFIX}/opt/openssl/include" -L"${PREFIX}/opt/openssl/lib" idapro-brute.c -o idapro-brute -lcrypto && ./idapro-brute
int main(int argc, char *argv[])
{
  // 3326487116: FgVQyXZY2XFk
  const char tgt[] = "f29f55f07c043ad34b3de150501535f44424edad";

  const char charset[] = "abcdefghijkmpqrstuvwxyzABCDEFGHJKLMPQRSTUVWXYZ23456789";
  int charset_len = (int) ((sizeof(charset)/sizeof(char)) - 1);
  const size_t N = 12;
  unsigned char *buf = (unsigned char*)malloc(sizeof(unsigned char)*(N*2+1));
  memset(buf,'\0',(N*2+1)*sizeof(unsigned char));
  long i = 0;
  if (argc >= 2)
  {
    char *ptr = NULL;
    i = strtol(argv[1],&ptr,10);
  }
  while (i < 0x100000000)
  {
    srand48(i);
    for (size_t n=0; n<N*2; n+=2) // UTF16LE
    {
      double r = drand48();
      int k = (int) (r * charset_len);
      buf[n] = charset[k];
    }

    const size_t SHA_DIGEST_LENGTH = 20;
    OpenSSL_add_all_algorithms();
    unsigned char *hash = (unsigned char*)malloc(sizeof(unsigned char)*(SHA_DIGEST_LENGTH+1));
    memset(hash,'\0',(SHA_DIGEST_LENGTH+1)*sizeof(unsigned char));
    unsigned int md_len = -1;
    const EVP_MD *md = EVP_get_digestbyname("SHA1");
    if (md != NULL)
    {
      EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
      EVP_DigestInit_ex(mdctx,md,NULL);
      EVP_DigestUpdate(mdctx,buf,N*2);
      EVP_DigestFinal_ex(mdctx,hash,&md_len);
      EVP_MD_CTX_destroy(mdctx);
    }
    char *hash_s = (char*)malloc(sizeof(char)*(SHA_DIGEST_LENGTH*2+1));
    memset(hash_s,'\0',(SHA_DIGEST_LENGTH*2+1)*sizeof(char));
    for (int j=0; j<SHA_DIGEST_LENGTH; j++)
    {
      sprintf((char*)&(hash_s[j*2]),"%02x",hash[j]);
    }
    if (hash != NULL) {free(hash);hash=NULL;}
    int eq = strcmp(hash_s,tgt) == 0;
    printf("i=%ld passwd:",i);
    for (size_t n=0; n<N*2; n+=2) {printf("%c",buf[n]);}
    printf(" sha1:%s ==tgt?%d\n",hash_s,eq);
    if (hash_s != NULL) {free(hash_s);hash_s=NULL;}
    i++;
    if (eq) {break;}
  }
  if (buf != NULL) {free(buf);buf=NULL;}
  return 0;
}

對其進行一些修改

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <string>

// $ innoextract --show-password IDA-Pro-v7.2.exe
// Inspecting "IDA Pro v7.2 and Hex-Rays Decompiler (x64)" - setup data version 5.5.7 (unicode)
// Password hash: SHA-1 f29f55f07c043ad34b3de150501535f44424edad
// Password salt: 50617373776f7264436865636b48617368c41639792846e456 (hex bytes, prepended to password)
// Password encoding: UTF-16LE
// hashcat -m 140 sha1($salt.utf64le($pass))
// gcc -I"${PREFIX}/opt/openssl/include" -L"${PREFIX}/opt/openssl/lib" idapro-brute.c -o idapro-brute -lcrypto && ./idapro-brute
int main2(int argc, char *argv[])
{
    // 3326487116: FgVQyXZY2XFk
    const char tgt[] = "f29f55f07c043ad34b3de150501535f44424edad";

    const char charset[] = "abcdefghijkmpqrstuvwxyzABCDEFGHJKLMPQRSTUVWXYZ23456789";
    int charset_len = (int) ((sizeof(charset)/sizeof(char)) - 1);
    const size_t N = 12;
    unsigned char *buf = (unsigned char*)malloc(sizeof(unsigned char)*(N*2+1));
    memset(buf,'\0',(N*2+1)*sizeof(unsigned char));

    char *salt = "50617373776f7264436865636b48617368c41639792846e456";
    //PasswordCheckHash
    //

    unsigned char salts[ strlen((salt)) / 2 ];
    char tmp[3] = {0};
    for (int l = 0, y=0; l < strlen((const char*)salt); l+=2, y++) {
        memcpy(tmp, salt+l, 2);
        long byte = strtol(tmp, NULL, 16);
        salts[y] = static_cast<unsigned char>(byte);
    }

    long i = 0;
//    i = 948301080;
//    i = 3326487116;
    if (argc >= 2)
    {
        char *ptr = NULL;
        i = strtol(argv[1],&ptr,10);
    }
    while (i < 0x100000000)
    {
        srand48(i);
        drand48();
        for (size_t n=0; n<N*2; n+=2) // UTF16LE
//        for (size_t n=0; n<N*1; n+=1) // UTF16LE
        {
            double r = drand48();
            int k = (int) (r * charset_len);
            buf[n] = charset[k];
        }

        const size_t SHA_DIGEST_LENGTH = 20;
        OpenSSL_add_all_algorithms();
        unsigned char *hash = (unsigned char*)malloc(sizeof(unsigned char)*(SHA_DIGEST_LENGTH+1));
        memset(hash,'\0',(SHA_DIGEST_LENGTH+1)*sizeof(unsigned char));
        unsigned int md_len = -1;
        const EVP_MD *md = EVP_get_digestbyname("SHA1");
        if (md != NULL)
        {
            EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
            EVP_DigestInit_ex(mdctx,md,NULL);

            EVP_DigestUpdate(mdctx,salts,strlen((salt)) / 2);
            EVP_DigestUpdate(mdctx,buf,N*2);

            EVP_DigestFinal_ex(mdctx,hash,&md_len);
            EVP_MD_CTX_destroy(mdctx);
        }
        char *hash_s = (char*)malloc(sizeof(char)*(SHA_DIGEST_LENGTH*2+1));
        memset(hash_s,'\0',(SHA_DIGEST_LENGTH*2+1)*sizeof(char));
        for (int j=0; j<SHA_DIGEST_LENGTH; j++)
        {
            sprintf((char*)&(hash_s[j*2]),"%02x",hash[j]);
        }
        if (hash != NULL) {free(hash);hash=NULL;}
        int eq = strcmp(hash_s,tgt) == 0;
        printf("i=%ld passwd:",i);
        for (size_t n=0; n<N*2; n+=2) {
            printf("%c",buf[n]);
        }
        printf(" sha1:%s ==tgt?%d\n",hash_s,eq);
        if (hash_s != NULL) {free(hash_s);hash_s=NULL;}
        i++;
        if (eq) {break;}
    }
    if (buf != NULL) {free(buf);buf=NULL;}
    return 0;
}

 

可以跑出7.2和6.8。後來看到https://bbs.pediy.com/thread-248989-2.htm有一個,也是7.0的跑不出來。

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//////////////////////////////////////////////////////////////////////////
// Perl rand (SVID Random Number)
#include <math.h>
#include <stdint.h>

#define FREEBSD_DRAND48_SEED_0 (0x330e)
#define DRAND48_MULT ((uint64_t)(0x5deece66dul))
#define DRAND48_ADD 0xb
#define DRAND48_MASK ((uint64_t)(0xfffffffffffful))

static uint64_t PL_random_state;
void pl_drand48_init_r(uint64_t* random_state, uint32_t seed)
{
    *random_state = FREEBSD_DRAND48_SEED_0 + ((uint64_t)seed << 16);
}

double pl_drand48_r(uint64_t* random_state)
{
    *random_state = (*random_state * DRAND48_MULT + DRAND48_ADD)
        & DRAND48_MASK;

    return ldexp((double)*random_state, -48);
}

#define pl_srand(seed) (pl_drand48_init_r(&PL_random_state, (seed)))
#define pl_drand48() (pl_drand48_r(&PL_random_state))

//////////////////////////////////////////////////////////////////////////
// SHA1
//
#define BLOCK_LEN 64 // In bytes
#define STATE_LEN 5 // In words

extern void sha1_compress(uint32_t state[STATE_LEN], const uint8_t block[BLOCK_LEN]);
//#include "sha1-fast.c"
void sha1_hash(const uint8_t message[], size_t len, uint32_t hash[STATE_LEN])
{
    hash[0] = UINT32_C(0x67452301);
    hash[1] = UINT32_C(0xEFCDAB89);
    hash[2] = UINT32_C(0x98BADCFE);
    hash[3] = UINT32_C(0x10325476);
    hash[4] = UINT32_C(0xC3D2E1F0);

#define LENGTH_SIZE 8 // In bytes

    size_t off;
    for (off = 0; len - off >= BLOCK_LEN; off += BLOCK_LEN)
        sha1_compress(hash, &message[off]);

    uint8_t block[BLOCK_LEN] = { 0 };
    size_t rem = len - off;
    memcpy(block, &message[off], rem);

    block[rem] = 0x80;
    rem++;
    if (BLOCK_LEN - rem < LENGTH_SIZE) {
        sha1_compress(hash, block);
        memset(block, 0, sizeof(block));
    }

    block[BLOCK_LEN - 1] = (uint8_t)((len & 0x1FU) << 3);
    len >>= 5;
    for (int i = 1; i < LENGTH_SIZE; i++, len >>= 8)
        block[BLOCK_LEN - 1 - i] = (uint8_t)(len & 0xFFU);
    sha1_compress(hash, block);
}

void print_hash(uint32_t hash[STATE_LEN])
{
    printf("%08x%08x%08x%08x%08x", hash[0], hash[1], hash[2], hash[3], hash[4]);
}

//////////////////////////////////////////////////////////////////////////
// IDA Key

char charset[] = "abcdefghijkmpqrstuvwxyzABCDEFGHJKLMPQRSTUVWXYZ23456789";

void key_hash(const char key[12], const uint8_t salt[8], uint32_t hash[STATE_LEN])
{
    // sha1("PasswordCheckHash"+salt+key)
    uint8_t msg[128] = { 0 };
    size_t msgLen = strlen("PasswordCheckHash");
    memset(msg, 0, sizeof(msg));
    memcpy(msg, "PasswordCheckHash", msgLen);
    memcpy(msg + msgLen, salt, 8);
    msgLen += 8;
    for (int i = 0; i < 12; i++) {
        msg[msgLen] = key[i];
        msgLen++;
    }
    sha1_hash(msg, msgLen, hash);
}

void key_hash_with_unicode(const char key[12], const uint8_t salt[8], uint32_t hash[STATE_LEN])
{
    // sha1("PasswordCheckHash"+salt+key)
    uint8_t msg[128] = { 0 };
    size_t msgLen = strlen("PasswordCheckHash");
    memset(msg, 0, sizeof(msg));
    memcpy(msg, "PasswordCheckHash", msgLen);
    memcpy(msg + msgLen, salt, 8);
    msgLen += 8;
    for (int i = 0; i < 12; i++) {
        msg[msgLen] = key[i];
        msgLen+=2;
    }
    sha1_hash(msg, msgLen, hash);
}

static void key_68()
{
    // PRAND: Perl>=5.2 default config. drand48 SVID Random Number
    // https://www.gnu.org/software/libc/manual/html_node/SVID-Random.html

    // 09db6f9a7e340f75606964cb69e2f3765dec5638
    // FgVQyXZY2XFk
    char key[13] = { 0 };
    pl_srand(3326487116);
    for (unsigned i = 0; i < 12; i++) {
        int64_t rnd = (int64_t)(pl_drand48() * (sizeof(charset) - 1));
        key[i] = charset[rnd];
    }
    printf("Key 6.8: real=\"FgVQyXZY2XFk\", calc = %s\nHASH=", key);

    uint32_t hash[STATE_LEN];
    const uint8_t salt[8] = { 0x95, 0xDF, 0x88, 0x3C, 0xCD, 0xEC, 0xDF, 0x52 };
    key_hash(key, salt, hash);
    print_hash(hash);
    printf("\n\n");
}

static void key_70()
{
    //PRAND: Perl<5.20 + MSVC LCG
    //https://en.wikipedia.org/wiki/Linear_congruential_generator

    //PasswordHash = 7ba6f1df9b88a25c6c5da522ccc307248aa0ec62;
    //PasswordSalt = 846e85474512dff8
    //Password = qY2jts9hEJGy
    char key[13] = "qY2jts9hEJGy";
    unsigned seed = 3133522587;
    seed = 0;
    unsigned found = 0;
    for (; seed < UINT_MAX; seed++) {
        srand(seed);
        for (unsigned i = 0; i < 12; i++) {
            int64_t rnd = (int64_t)((double)rand() / RAND_MAX * (sizeof(charset) - 1));
            if (key[i] != charset[rnd])
                break;
            if (i == 11) {
                found = 1;
            }
        }
        if (found) {
            break;
        }
    }
    if (!found) {
        printf("Key 7.0 NOT FOUND!!!\n");
        return;
    }
    printf("Key 7.0: key=\"qY2jts9hEJGy\", seed = %u\nHASH=",
        seed);

    uint32_t hash[STATE_LEN];
    const uint8_t salt[8] = { 0x84, 0x6e, 0x85, 0x47, 0x45, 0x12, 0xdf, 0xf8 };
    key_hash(key, salt, hash);
    print_hash(hash);
    printf("\n\n");
}

static void key_72()
{
    // PRAND: Perl>=5.20 drand48 + 1st rand omitted

    // PasswordHash = f29f55f07c043ad34b3de150501535f44424edad
    // PasswordSalt = c41639792846e456
    // Password = 7JpT48a7Y2fv
#define KEY_LEN 12
    char key[KEY_LEN + 1] = { 0 };
    unsigned found = 0;
    unsigned seed = 948301080;
    seed = 0;

    uint32_t hash[STATE_LEN];
    const uint8_t salt[8] = { 0xc4, 0x16, 0x39, 0x79, 0x28, 0x46, 0xe4, 0x56 };
    const uint32_t real_hash[STATE_LEN] = { 0xf29f55f0, 0x7c043ad3, 0x4b3de150, 0x501535f4, 0x4424edad };

    for (; seed < UINT_MAX; seed++) {
        pl_srand(seed);
        pl_drand48();  // 去掉第一個random number
        for (unsigned i = 0; i < KEY_LEN; i++) {
            int64_t rnd = (int64_t)(pl_drand48() * (sizeof(charset) - 1));
            key[i] = charset[rnd];
        }
        key_hash_with_unicode(key, salt, hash);
        if (memcmp(hash, real_hash, sizeof(hash)) == 0) {
            found = 1;
            break;
        }
    }
    if (!found) {
        printf("Key 7.2 NOT FOUND!!!\n");
        return;
    }
    printf("Key 7.2: key=%s, seed = %u\nHASH=",
        key, seed);

    print_hash(hash);
    printf("\n\n");
}

int main()
{
    key_68();
    key_70();
    key_72();

    return 0;
}
/* 
 * SHA-1 hash in C
 * 
 * Copyright (c) 2017 Project Nayuki. (MIT License)
 * https://www.nayuki.io/page/fast-sha1-hash-implementation-in-x86-assembly
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * - The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 * - The Software is provided "as is", without warranty of any kind, express or
 *   implied, including but not limited to the warranties of merchantability,
 *   fitness for a particular purpose and noninfringement. In no event shall the
 *   authors or copyright holders be liable for any claim, damages or other
 *   liability, whether in an action of contract, tort or otherwise, arising from,
 *   out of or in connection with the Software or the use or other dealings in the
 *   Software.
 */

#include <stdint.h>


void sha1_compress(uint32_t state[5], const uint8_t block[64]) {
	#define ROTL32(x, n)  (((0U + (x)) << (n)) | ((x) >> (32 - (n))))  // Assumes that x is uint32_t and 0 < n < 32
	
	#define LOADSCHEDULE(i)  \
		schedule[i] = (uint32_t)block[i * 4 + 0] << 24  \
		            | (uint32_t)block[i * 4 + 1] << 16  \
		            | (uint32_t)block[i * 4 + 2] <<  8  \
		            | (uint32_t)block[i * 4 + 3] <<  0;
	
	#define SCHEDULE(i)  \
		temp = schedule[(i - 3) & 0xF] ^ schedule[(i - 8) & 0xF] ^ schedule[(i - 14) & 0xF] ^ schedule[(i - 16) & 0xF];  \
		schedule[i & 0xF] = ROTL32(temp, 1);
	
	#define ROUND0a(a, b, c, d, e, i)  LOADSCHEDULE(i)  ROUNDTAIL(a, b, e, ((b & c) | (~b & d))         , i, 0x5A827999)
	#define ROUND0b(a, b, c, d, e, i)  SCHEDULE(i)      ROUNDTAIL(a, b, e, ((b & c) | (~b & d))         , i, 0x5A827999)
	#define ROUND1(a, b, c, d, e, i)   SCHEDULE(i)      ROUNDTAIL(a, b, e, (b ^ c ^ d)                  , i, 0x6ED9EBA1)
	#define ROUND2(a, b, c, d, e, i)   SCHEDULE(i)      ROUNDTAIL(a, b, e, ((b & c) ^ (b & d) ^ (c & d)), i, 0x8F1BBCDC)
	#define ROUND3(a, b, c, d, e, i)   SCHEDULE(i)      ROUNDTAIL(a, b, e, (b ^ c ^ d)                  , i, 0xCA62C1D6)
	
	#define ROUNDTAIL(a, b, e, f, i, k)  \
		e = 0U + e + ROTL32(a, 5) + f + UINT32_C(k) + schedule[i & 0xF];  \
		b = ROTL32(b, 30);
	
	uint32_t a = state[0];
	uint32_t b = state[1];
	uint32_t c = state[2];
	uint32_t d = state[3];
	uint32_t e = state[4];
	
	uint32_t schedule[16];
	uint32_t temp;
	ROUND0a(a, b, c, d, e,  0)
	ROUND0a(e, a, b, c, d,  1)
	ROUND0a(d, e, a, b, c,  2)
	ROUND0a(c, d, e, a, b,  3)
	ROUND0a(b, c, d, e, a,  4)
	ROUND0a(a, b, c, d, e,  5)
	ROUND0a(e, a, b, c, d,  6)
	ROUND0a(d, e, a, b, c,  7)
	ROUND0a(c, d, e, a, b,  8)
	ROUND0a(b, c, d, e, a,  9)
	ROUND0a(a, b, c, d, e, 10)
	ROUND0a(e, a, b, c, d, 11)
	ROUND0a(d, e, a, b, c, 12)
	ROUND0a(c, d, e, a, b, 13)
	ROUND0a(b, c, d, e, a, 14)
	ROUND0a(a, b, c, d, e, 15)
	ROUND0b(e, a, b, c, d, 16)
	ROUND0b(d, e, a, b, c, 17)
	ROUND0b(c, d, e, a, b, 18)
	ROUND0b(b, c, d, e, a, 19)
	ROUND1(a, b, c, d, e, 20)
	ROUND1(e, a, b, c, d, 21)
	ROUND1(d, e, a, b, c, 22)
	ROUND1(c, d, e, a, b, 23)
	ROUND1(b, c, d, e, a, 24)
	ROUND1(a, b, c, d, e, 25)
	ROUND1(e, a, b, c, d, 26)
	ROUND1(d, e, a, b, c, 27)
	ROUND1(c, d, e, a, b, 28)
	ROUND1(b, c, d, e, a, 29)
	ROUND1(a, b, c, d, e, 30)
	ROUND1(e, a, b, c, d, 31)
	ROUND1(d, e, a, b, c, 32)
	ROUND1(c, d, e, a, b, 33)
	ROUND1(b, c, d, e, a, 34)
	ROUND1(a, b, c, d, e, 35)
	ROUND1(e, a, b, c, d, 36)
	ROUND1(d, e, a, b, c, 37)
	ROUND1(c, d, e, a, b, 38)
	ROUND1(b, c, d, e, a, 39)
	ROUND2(a, b, c, d, e, 40)
	ROUND2(e, a, b, c, d, 41)
	ROUND2(d, e, a, b, c, 42)
	ROUND2(c, d, e, a, b, 43)
	ROUND2(b, c, d, e, a, 44)
	ROUND2(a, b, c, d, e, 45)
	ROUND2(e, a, b, c, d, 46)
	ROUND2(d, e, a, b, c, 47)
	ROUND2(c, d, e, a, b, 48)
	ROUND2(b, c, d, e, a, 49)
	ROUND2(a, b, c, d, e, 50)
	ROUND2(e, a, b, c, d, 51)
	ROUND2(d, e, a, b, c, 52)
	ROUND2(c, d, e, a, b, 53)
	ROUND2(b, c, d, e, a, 54)
	ROUND2(a, b, c, d, e, 55)
	ROUND2(e, a, b, c, d, 56)
	ROUND2(d, e, a, b, c, 57)
	ROUND2(c, d, e, a, b, 58)
	ROUND2(b, c, d, e, a, 59)
	ROUND3(a, b, c, d, e, 60)
	ROUND3(e, a, b, c, d, 61)
	ROUND3(d, e, a, b, c, 62)
	ROUND3(c, d, e, a, b, 63)
	ROUND3(b, c, d, e, a, 64)
	ROUND3(a, b, c, d, e, 65)
	ROUND3(e, a, b, c, d, 66)
	ROUND3(d, e, a, b, c, 67)
	ROUND3(c, d, e, a, b, 68)
	ROUND3(b, c, d, e, a, 69)
	ROUND3(a, b, c, d, e, 70)
	ROUND3(e, a, b, c, d, 71)
	ROUND3(d, e, a, b, c, 72)
	ROUND3(c, d, e, a, b, 73)
	ROUND3(b, c, d, e, a, 74)
	ROUND3(a, b, c, d, e, 75)
	ROUND3(e, a, b, c, d, 76)
	ROUND3(d, e, a, b, c, 77)
	ROUND3(c, d, e, a, b, 78)
	ROUND3(b, c, d, e, a, 79)
	
	state[0] = 0U + state[0] + a;
	state[1] = 0U + state[1] + b;
	state[2] = 0U + state[2] + c;
	state[3] = 0U + state[3] + d;
	state[4] = 0U + state[4] + e;
}

 

打開VC命令行工具
cl /O2 ida_pwd.c sha1-fast.c

難道是因爲我是mac的,要試試windows的vc?

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章