Reverseme Windows Keygen

This one was challenging for me, and took me several hours, but was fun. I got caught up on certain parts that may not have been too difficult, but, yeah…

http://crackmes.de/users/tripletordo/ice9/

You can download the executable here Ice9.zip.

The first thing I noticed is probably the ‘trick’ which was simply a call to isdebuggerpresent. I modified the assembly immediately after from JNE to JE so that it only runs if a debugger is present, allowing me to attach my debugger.

00401071 74 0A JE SHORT Ice9.0040107D

This took a lot of trial and error. My strategy was to replicate the logic. Once I got to the point ‘ecx at 0040119c’ I was home free.

#include <iostream>
#include <string>
using namespace std;

void main (int argc, char *argv[]) {
  if ( argc != 2) {
    cout<<"Bad usage, enter a name > 4 letters"<<endl;
	return;
  }
  string name = argv[1];
  string ostring = name;
  int i;
  //first reverse the string
  for (i=0; i<name.length(); i++) {
    name[i] = ostring [name.length()-i-1];
  }
  
  if (name.length() < 4) {
    cout << "name must be more than 4 letters chief"<<endl;
	return;
  }
  

  int v1 = 0;
  int cum = 0;
  for (i=1; i<name.length(); i++) {
    v1 = name[i];
	if (name[i] <= 90) {
	  if (v1 >= 65)
	    v1 += 44;
	}
	cum += v1;
  } //ecx at 0040119C
  
  cum = 9 * (12345 * (cum + 666) - 23);
  
  char chr_403119 [122];
  unsigned int v;
  i=0;
  //no bounds checking
  do {
    v = cum;
	cum /= 0xA;
	chr_403119[i++] = v % 10 + 48;
  } while (v / 10);
  chr_403119[i] = '\0';
  
  printf ("%s", chr_403119);
  string serial = "";

  //reverse the string
  for (; i >= 0; --i) {
    serial += chr_403119[i];
  }
  cout<<serial<<endl;
  
  //append all chars except the 'first' three to the end 
  for (i=3; i< ostring.length(); i++) {
    serial += ostring[i];
  }
  
  cout<<serial<<endl;

}

My plan on this one, since it was interesting enough and because it’s relatively easy to break at the final value, is to break this a completely different way. I’d like to write a python debugging script that bypasses the isdebuggerpresent and just grabs the final value in the compare at 004011FF. This should be relatively straightforward, and hopefully a good ‘hello, world’ to the world of python debugging. Stay tuned.

Nmap script to detect Debian OpenSSL Random Number Generator Weakness

This relies on HD’s keys, found http://digitaloffense.net/tools/debian-openssl/

description = [[
Debian OpenSSH/OpenSSL Package Random Number Generator Weakness
]]

---
-- @output
-- 22/ssh open  ssh
-- |_ ssh_debian_weak: The following keys are vulnerable: 2048 RSA 1024 RSA

-- SSH Weak Debian Key Script
-- rev 1.0 (2010-02-07)
-- rougly based on ssh_debian_weak.nasl by tennable
-- written by hand

author = "Rich Lundeen <mopey@webstersprodigy.net>"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"websters", "nessus", "act_gather_info"}

dependencies = {"ssh-hostkey"}

require("shortport")
require("ssh1")
require("ssh2")
require("nessus/nessus_conf")
portrule = shortport.port_or_service({22}, {"ssh"})

action = function(host, port)
  local keyval = nmap.registry.sshhostkey[host.ip]
  if keyval == nil then
    return
  end
  local output = ""
  for i,line in ipairs(keyval) do
    --TODO eventually binary search is nicer, but due to formats ready from HD
    --or if wanted later perhaps add the hex version to registry
    local linekey = string.gsub(ssh1.fingerprint_hex(line.fingerprint, 
                                line.algorithm, line.bits), ":", "")
    local crimp = pcre.new("^[^\s]+[\s]([^\s]+)[\s][^\s]+", 0, "C")
    local s, e, t = crimp:exec(linekey, 0, 0)
    linekey = string.sub(linekey, t[1], t[2])
    local fstring = (nessus_conf.nessus_conf["basedir"] .. 
                     "nselib/nessus/data/debian_weak_ssl/" .. 
                     line.algorithm:lower() .. "_" .. 
                     tostring(line.bits))
    local mfile = io.open(fstring, "r")
    for vulnkey in mfile:lines() do
      --TODO this could be made more efficient
      if string.find(vulnkey, linekey, 0) then
        output = output .. line.algorithm .. " " .. tostring(line.bits)
      end
    end
    mfile:close()
  end
  if output ~= "" then
    return output
  end
end

Reverseme: Namegenme

This guy is here: http://crackmes.de/users/moofy/moofys_namegenme/

namegenme.zip

I had a fairly hard time with this one for some reason, although the solution was right in front of my face…

Most the logic for calculating the generation is in the function 00401852. The Serial is stored in a global variable, and the name is generated by taking certain bytes from the serial and doing addition on them.

Here is all the relevant logic, although finding it was sort of a pain.


.text:004018FD                 lea     eax, [ebp+var_10]
.text:00401900                 add     dword ptr [eax], 4
.text:00401903                 lea     eax, [ebp+var_14]
.text:00401906                 sub     dword ptr [eax], 3
.text:00401909                 lea     eax, [ebp+var_18]
.text:0040190C                 sub     dword ptr [eax], 2
.text:0040190F                 lea     eax, [ebp+var_1C]
.text:00401912                 add     dword ptr [eax], 2
.text:00401915                 lea     eax, [ebp+var_20]
.text:00401918                 dec     dword ptr [eax]
.text:0040191A                 lea     eax, [ebp+var_24]
.text:0040191D                 add     dword ptr [eax], 3
.text:00401920                 lea     eax, [ebp+var_28]
.text:00401923                 sub     dword ptr [eax], 2
.text:00401926                 lea     eax, [ebp+var_2C]
.text:00401929                 sub     dword ptr [eax], 4
.text:0040192C                 lea     eax, [ebp+var_30]
.text:0040192F                 add     dword ptr [eax], 3
.text:00401932                 lea     eax, [ebp+var_34]
.text:00401935                 inc     dword ptr [eax]

Here is a keygen written in C

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

  char Name [10];
  char* ser = argv[1];
  if (argc != 2 || strlen(argv[1]) < 21) {
    printf("Invalid serialn");
	return (-1);
  }

  Name[0] = ser[0] + 4;
  Name[1] = ser[1] - 3;
  Name[2] = ser[2] - 2;
  Name[3] = ser[6] + 2;
  Name[4] = ser[7] - 1;
  Name[5] = ser[8] + 3;
  Name[6] = ser[13] - 2;
  Name[7] = ser[14] - 4;
  Name[8] = ser[15] + 3;
  Name[9] = ser[20] + 1;
  Name[10] = "\0";

  printf("Name: %sn", Name);
}

Reverseme: Easy Windows Using Reflector

http://crackmes.de/users/d0min4ted/keygenme_by_d0min4ted/

In case the link goes away, here is a zip of the executable. crackme

I cheated on this one and used reflector. This was an excuse for me to try reflector out… so I started with that in mind.

The Checking code ends up being in crackme->WindowsFormsApplication4->Form1. You can deduce what most the buttons do. The relevant one turns out to be in asd. The keygen is basically straight from the verifying function found there, written in C#.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace keygen
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Name: ");
            string Name = Console.ReadLine();
            if (Name.Length < 4)
            {
                Console.WriteLine("Name must be 4 characters");
                Environment.Exit(0);
            }

            string str3 = "";
            char[] chArray = Name.ToCharArray();
            foreach (char ch in chArray)
            {
                int num2 = Convert.ToInt32(ch);
                string str4 = string.Format("{0:X}", num2);
                str3 = str3 + str4;
            }
            char[] array = str3.ToCharArray();
            Array.Reverse(array);
            string str5 = new string(array);
            if (str5.Length > 9)
            {
                str5 = str5.Remove(9, str5.Length - 9);
            }
            decimal num4 = Convert.ToDecimal(Convert.ToInt32(str5));
            double num5 = Math.Pow((double)Name.Length, 3.0);
            decimal num6 = Math.Round((decimal)(num4 * Convert.ToDecimal(num5)), 0);
            Console.WriteLine(num6);
        }
    }
}

Reverseme: Easy Windows

To get back into the groove, I decided to try a crackme. After searching far and wide, I can’t seem to find where I got this from, other than crackmes.de.  One of my favorite sites.

Crackme.zip <– here it is in case it’s deleted.

And the solution is, with no analysis:


#include <iostream>
#include <string>
using namespace std;

int add_name_chars(string name) {
  int total = 0;
  for (int i=0; i<name.length(); i++) {
    total += name[i];
  }
  return total;
}

int main() {
  string name;
  cout<<"Name: ";
  cin>>name;

  unsigned int ser1 = 31 * add_name_chars(name) / 629u + 44431400;
  while (ser1 > 0x3b9ac9ff) {
    ser1 /= 10;
  }
  cout<<"Serial 1: "<<ser1<<endl;

  unsigned int ser2 = 82 * ser1 - 3;
  while (ser2 > 0x1869f)  {
    ser2 /= 10;
  }

  cout<<"Serial 2: "<<ser2<<endl;
  return 0;
}

Ok, one hint. All the logic is at 004013BC. This was rated as 1, for newbies, but it still took me awhile to figure out. I thought it was fun.

Follow

Get every new post delivered to your Inbox.