Improving Meltdown

kao

More than 2 years ago I released Meltdown. It's a proof-of-concept tool that showed several security issues in Faronics DeepFreeze products. Faronics are infamous for their attempts to hide the issues, so I was really curious how it will work out.

Bugs in my code

First, a few bugs in my code surfaced. None of them were in the core components dealing with DeepFreeze, I had that part tested thoroughly. But I overlooked issues with UAC, possibility that Windows are not installed on drive C:\, empty passwords and other edge cases.

All in all, it was a good learning experience.

Requests for source code

The very first version of Meltdown came with a full source code and explanation of the vulnerabilities in Faronics products. Once I started fixing bugs, I released only the updated binary. Yet quite a few people kept asking for the updated source.

To be honest, I have no idea why. So far, I haven't seen a single tool that would be based on my source code, not even a straightforward rip with a changed name and copyrights. Weird..

Bug reports

People reported bugs. Big bugs, small bugs, non-bugs and everything in between.

Most bug reports came from arabic-speaking guys. Some of them even didn't bother to use Google Translate and wrote in their native language. No, I really don't speak Arabic, German, French or Indonesian.

Also, most bug reports came without any actionable information whatsoever. Just "It doesn't work". Well, that's not helpful at all! I really want to help you, but you must tell me more than that. In later versions, I added information to main window about detected OS, 32/64bits, detected DF version, etc, etc. And then I can just ask for a screenshot, it contains most of the info I need to replicate the issue.

It was a good learning experience again. I learned how to make my tools more user-proof.

Faronics response

For a year, there was none.

Then in June 2014 they released DeepFreeze Enterprise 8.11 where the issue was fixed. At least the changelog says so:

7936 Resolved a security issue that could result in the user accessing Deep Freeze without authorization.

Yeah, right.. In reality they just added yet-another-layer of xor-encryption and removed useful data from frzstate2k.exe. But the same data are still present in dfserv.exe.

Wow, that's what I call "resolving a security issue"! πŸ™‚

In September 2014 they released DeepFreeze Standard 8.10 where the other vulnerability was fixed. However, there was no mention of anything like that in the changelog. From a quick glance, it looks like they finally got their code right and aren't sending xor-encrypted password from driver to usermode anymore.

What now?

I'm presenting you an updated version of Meltdown.

Meltdown v1.5
It shows that vulnerabilities in Enterprise version are still present, just slightly more obfuscated. But security through obscurity does not work!

The glaring vulnerability in Standard version is fixed, and 8.x Standard versions seem to be safe. Funny, isn't it - you'd expect a corporate product to provide better security than home-edition, yet this is not the case.. πŸ™‚

Download link for Meltdown v1.5: http://www.mediafire.com/?0wc0vv1kauhwxbb

How to learn Reverse Engineering

kao

Every other days or two a new guy appears at Tuts4You asking "I want to learn Reverse Engineering, where do I start?".

Hmmm...

There are lots of suggestions, eg. in this Reddit thread. One of the most common recommendation is to with Lena151's tutorials. And there's a good reason for that - these tutorials give a good overview of most common tasks, most common tools and provide "instant gratification". But do they actually teach you Reverse Engineering? I don't think so.

Why Lena151's tutorials are bad

Apparently I'm not the only one who thinks so:

I have been thinking about why this happens. Thinking back to myself, I started learning reverse engineering by reading the Lena151 tutorials. I thought they were awesome until Daeken told me that was an awful approach to learn reverse engineering.

At first I didn’t understand why they were so bad. After all, Lena’s tutorials had taught me how to crack my first software.

And that's exactly the problem. You managed to crack your first software. Instant gratification! But what did you actually learn? Run some common tools, find the "bad boy jump" and patch it? Wow! You must be so l33t!

In reality, these tutorials have produced entire generation of wanna-be-crackers who can only use ready-made tools, but are actually unable to think for themselves. For every problem they need a video tutorial. For every small obstacle they create a new topic asking for help.

And that's only half of the problem.

Video tutorials made by beginners are even worse

Albert Einstein once said:

The more I learn, the more I realize how much I don't know.

Beginners who watched Lena151's series don't realize that. They cracked their first program and they consider themselves to be reversers. And what's even worse, they try to spread their "knowledge" by making an incredible amount of incredibly crappy video "tutorials" to be watched by next generation of wannabes.

I've actually watched a 15 minute movie titled "How to unpack CryptoObfuscator". You know how? You drag-and-drop the file on de4dot. Yes, that simple. Yes, someone made 15 minute movie to teach you that.

So, what's the alternative?

ReverseWithMe blog suggests to learn:

  1. x86 assembly (electronics and wires in the car analogy)
  2. How operating systems work and how they manage memory (the engine of the car)
  3. The compiling process from C-code to assembly (this is equivalent to knowing how a car-fabric is assembling a car)
  4. The life of a binary (equivalent to everything that happens in the car from the key-switch to the off-switch)

I don't think this is the correct approach either.

It's like learning a foreign language by reading a dictionary. Start with an "a", and once you finish with "z", you'll know all the words. Maybe. But you won't be able to make a proper sentence, let alone speak or understand a native speaker.

To put it into context: I've been reversing .NET executables for 10 years now. I've written unpackers for pretty much every .NET protection there is. And yet I still don't know IL assembly "by heart". Why? Because I don't need to. What's the mnemonic for "branch-if-equal"? Is it be, beq or bre? Does it pop one or two arguments from stack? I don't know. If I'll ever need that, the answer is one Google search away.

Yes, to be a great reverser, you will need to master most of those items. But you don't need to know all that at the start of your journey.

Gimme a solution, goddamit!

Well, start with Lena151's tutorials. Yes, I said they are not good, but that's the best there is. And if you follow few extra advices, you'll do just fine:

  • Learn to think for yourself. That's the most important part. Don't just blindly follow tutorials, try to understand why it works and how it works.
  • Learn to search. Most questions have already been answered, you just need to find the answer. Make sure Google is your friend!
  • Learn your tools. You don't need to know every single option and feature of them. Most people use ~10% of all Microsoft Excel features. Power Users use around 20%. It's the same with RE tools. If you've mastered 10% of Olly or IDA features, you're good to go.
  • And last but not least - have fun! Nothing kills your productivity faster than boredom. If the problem is too hard, let it go, try something else and come back to it later.

Sniffing correct serial in .NET crackmes

kao

Introduction

In this tutorial I'll show you a generic way how to break most of the crackmes written in VB.NET. It uses the fact that most crackmes made by beginners will calculate correct serial and do a simple comparison "if enteredSerial = correctSerial then"...

To break such a crackme, you only need to find this comparison and sniff the correct serial. This is a very common approach in x86 world but in .NET world it's not that popular yet.

As for my target, I'm using "RDG Simple Crackme .NET v4 2015"

GetProcAddress in .NET

In x86 world you can use GetProcAddress function to get address of any API function from any DLL. Can we do something similar in managed environment like .NET? It turns out that we can, but it's a little bit harder.

So, for example, to get address of Assembly.Load(byte[]) you need to do:

MethodBase mb = typeof(Assembly).GetMethod("Load", new Type[] { typeof(byte[]) });
IntPtr handle = mb.MethodHandle.GetFunctionPointer();
Console.WriteLine("Assembly.Load() = {0:X}", handle.ToInt32());

This works well with static classes and static methods. How about non-static methods like RijndaelManaged.CreateDecryptor(byte[], byte[])?

That's doable as well, like this:

RijndaelManaged rijndael = new RijndaelManaged();
mb = rijndael.GetType().GetMethod("CreateDecryptor", new Type[] { typeof(byte[]), typeof(byte[]) });
handle = mb.MethodHandle.GetFunctionPointer();
Console.WriteLine("RijndaelManaged.CreateDecryptor() = {0:X}", handle.ToInt32());

To make this reference almost complete - here's how to get address of .ctor:

ConstructorInfo ctor = typeof(MyClass).GetConstructor(Type.EmptyTypes);
IntPtr ctorPtr = ctor.MethodHandle.GetFunctionPointer();
Console.WriteLine("MyClass constructor = {0:X}", ctorPtr.ToInt32());

There are a few gotchas, however..

  • In case your target type is located in assembly that's not NGEN'ed yet, I suggest that you use ngen and install the assembly in cache. That can prevent certain problems later.
  • Addresses of functions are obviously different in .NET 2.0 and 4.0. You must compile for correct framework version and target the correct .NET assembly.
  • Addresses of functions are different for x86 and x64 framework versions, too. Make sure your assembly is compiled correctly.

Sniffing string compare

Suprisingly, string comparison in VisualBasic.NET and other .NET languages is different. It's caused by Option Compare statement present in Visual Basic language. So, if the crackme is made in VB.NET, you need to examine Operators.CompareString(string,string,bool) function. For crackmes made in other languages, you'll need to examine string.Equals(string) or some other variation of this method.

So, using the code I mentioned above, I learned that address of Operators.CompareString(string,string,bool) on my PC is 599F1D30. Now I need to sniff data passed to this function.

There are several possible approaches. You can try using VisualStudio & Reflector plugin as SpoonStudio tried, you can try using ILSpy and it's debugger plugin, or you can inject DLL into crackme process, as suggested by noth!ng - but I prefer to use OllyDbg.

Load crackme in OllyDbg, make sure that all the anti-anti-debug plugins are working, all the exceptions ignored, put a breakpoint on 599F1D30 and hope for the best.

Nope. Operators.CompareString is called literally thousands of times. So, we need to do something smarter.

For example, we can use conditional logging breakpoints in Olly. Those breakpoints are quite slow, but it's still faster than to write some sort of hooking DLL and inject it into crackme. So, we need to set 2 logging breakpoints - one for each string compared. Here is first one:
crackme_conditional_breakpoint
Place second breakpoint at the next instruction (59CD1D31) and log string at edx+8.

Run the crackme, enter some fake but easily recognizable serial and few minutes later we have the answer:
crackme_logged_results
My entered serial was "1234567890123456789012345678901234567890" and it's being compared to "C49476D583364356253377056314435396D456F44796C7A55746431564433544". Hmm, could that be the correct serial for my nickname? πŸ˜‰ Yes, it is!

Final notes

This was quite nice crackme and I only showed the simplest way to beat it. When you start looking into it, you'll find some nice anti-debug tricks, some nice anti-patching tricks and pretty nicely obfuscated code.

But that's a matter for another story. Have fun!

About e-governments

kao

Two days ago Google released Chrome 42. It's the answer to life, the universe and everything. And among other things, it disables all NPAPI plugins by default, finally putting that Java nightmare into it's grave. Good riddance!

But what about other NPAPI plugins? Like, you know, the ones used for electronic documents, digital signatures and other e-government thingies?

Well, here are 2 ways how government agencies approach the same problem:
e-governments compared

Welcome to the 21st century. If you're Estonian, that is..

Catch me when you can

kao

Introduction

Exception filters have been part of ECMA-335 specification since the very beginning. I'm guessing, they were added because Visual Basic used them extensively and therefore Visual Basic.NET had to support them as well. They look something like this:

Try
   'Try statements.
Catch cle As ClassLoadException When cle.IsRecoverable()
   'Catch statements.
End Try

Until now C# supported try/catch but did not have support for filters. That's going to change in C# 6.0/VS2015.

How does it work

In early versions of VS2015 the syntax was "catch-if", as you can see in the initial announcement. In the latest VS2015 CTP builds, they changed syntax to "catch-when", and there's a good reason for it.

So, how does it work and what does it mean for reversers?

It's a compiler-level feature

As I mentioned before, .NET Framework has supported exception filters since the very beginning. So, this feature works even in .NET 2.0 - if you decide to target .NET 2.0 Framework in VS2015 project settings. Not that you really want to do that..

It's very useful for debugging

catch-when is implemented as an IL exception filter. So, when an exception is thrown, exception filters are processed before the stack is unwound. This means that filter method has created an error report that included the current stack trace, it would show the frame in which the exception occurred. Sounds complicated? It isn't.

Let's implement exception filtering in the "old" way:

private void button2_Click(object sender, EventArgs e)
{
   try
   {
      ThisCanThrow();
   }
   catch (Exception ex)
   {
      if (filter(ex))
         textBox1.AppendText("Interesting exception");
      else
         throw(ex);
   }
}

and this is how the stack looks when we get to filter(ex):
stack_trace_old
You can't see much here. All the context is gone, you must rely on exception stack trace and message. That's what we've always done, right? πŸ™‚

If we write it in a "new" way, the code looks like this:

private void button1_Click(object sender, EventArgs e)
{
   try
   {
      ThisCanThrow();
   }
   catch (Exception ex) when (filter(ex))
   {
      textBox1.AppendText("Interesting exception");
   }
}

and stack trace will give us full context of exception:
stack_trace_new
Much better, isn't it? You can see which method threw the exception, on which line, you have access to local variables and everything else. Yummy! πŸ™‚

Decompiler support for exception filters is crappy

They say, a picture is worth thousand words.. In a very simple example, Reflector gets the code structure right, just filter conditions are missing:
catch_when_reflector
ILSpy handles it slightly worse, filters are messed up and unreadable. Filter code is gone, too:
catch_when_ilspy
And the latest JustDecompile just throws an exception:
catch_when_justdecompile

Have fun with it!

Here is a small keygen-me for you to play with: https://www.mediafire.com/?k5b9vy0p9dfgb97

The difficulty is 2/10, you should be able to solve it in 30 minutes or so. The entire protection is designed to show you try-catch-when feature, so avoid patching - you can't learn anything by nopping-out few instructions. πŸ˜‰

The malware arms race

kao

Today's Slashdot features a very nice question:

We've been in a malware arms race since the 1990s. Malicious hackers keep building new viruses, worms, and trojan horses, while security vendors keep building better detection and removal algorithms to stop them.
...
My question: will the balance continue, or is one side likely to take the upper hand over the next decade or two? Which side is going to win?
...

In the comments you'll see a lot of libertarian psychobabble about how NSA/CIA/{whatever-3-letter-organization} caused this, how you are going to surrender your fundamental rights to a few corporations who pretend to protect you, how everything sucks and will suck even more in the future.

Well, that IS Slashdot, afterall.

But this comment made my day so much better:
Idiots will lose

Have fun and keep your schlongs safe!

.NET, ScyllaHide and HEAP_CREATE_ENABLE_EXECUTE

kao

While doing some research on ILProtector, I loaded my test executable in Olly. To much of my surprise, it refused to run and all I could see in Olly log, was this:

Log data
Address    Message
           OllyDbg v1.10
           Command line: test.exe

           Console file 'C:\test.exe'
           ODbgScript v1.82.6 i686 VC2008 WDK7.1 CRT/STL60
             http://odbgscript.sf.net
           ScyllaHide Plugin v1.3
             Copyright (C) 2014 Aguila / cypher
           Hooked Olly Breakpoints handler for TLS at 0x2F918
           New process with ID 00002E2C created
00FC404E   Main thread with ID 00002754 created
           [ScyllaHide] Reading NT API Information C:\Tools\Olly\Plugins\NtApiCollection.ini
           [ScyllaHide] Hook Injection successful, Imagebase 00030000
00FC0000   Module C:\test.exe
             CRC changed, discarding .udd data
748C0000   Module C:\Windows\SYSTEM32\MSCOREE.DLL
             CRC changed, discarding .udd data
76070000   Module C:\Windows\syswow64\KERNEL32.dll
76180000   Module C:\Windows\syswow64\KERNELBASE.dll
             CRC changed, discarding .udd data
77100000   Module C:\Windows\SysWOW64\ntdll.dll
             CRC changed, discarding .udd data
771A103B   System startup breakpoint
76650000   Module C:\Windows\syswow64\ADVAPI32.dll
             CRC changed, discarding .udd data

...

5B820000   Module C:\Protect32.dll
             CRC changed, discarding .udd data
76840000   Module C:\Windows\syswow64\OLEAUT32.dll
             CRC changed, discarding .udd data
008B5BFF   Access violation when executing [008B5BFF]
7618C42D   Exception E0434F4D
7618C42D   Exception E06D7363
7618C42D   Exception E0434F4D
           Debugged program was unable to process exception

Something smells fishy! πŸ˜‰

I disabled all non-standard plugins, and I was still getting the exception. It was only after I removed the remaining 2 plugins (ScyllaHide and ODBGScript) that my test application launched. Few more restarts and I was sure that ScyllaHide is the one causing the trouble.

OK, I've found a bug in ScyllaHide. But where is it? Which option is causing it? And how can I fix it?

Unfortunately, there is no easy way. Just go through one option after another, until you trigger the bug. 10 minutes and 100 rude words later I was sure that "HeapFlags" is the culprit.

A side note from Captain Obvious

If you're seeing access violation in Olly and want to know where it's happening, make sure you uncheck Ignore Memory access violation in Debugging Options:
olly debugging options
and then run your target:
crash on jit stub
Here we can see that there is a real code at this address - small stub calling mscorwks.dll and that the call comes from ILProtector's protect32.dll.

It immediately gives you plenty of useful information about what's happening. Unfortunately I debugged one instance of Olly from another instance of Olly - got the same results but it took me much longer.

Meet HEAP_CREATE_ENABLE_EXECUTE

It turns out that .NET Runtime Execution Engine (mscoreei.dll) loves to put executable code on heap:

.text:1000A424 ; int __stdcall DllMainProcessAttach()
.text:1000A424 ?DllMainProcessAttach@@YGHXZ proc near  ; CODE XREF: DllMain(x,x,x):loc_1000A6B4p

...

.text:1000A591   push    ebx             ; dwMaximumSize
.text:1000A592   push    ebx             ; dwInitialSize
.text:1000A593   push    HEAP_CREATE_ENABLE_EXECUTE ; flOptions
.text:1000A598   call    ds:__imp__HeapCreate@12 ; HeapCreate(x,x,x)
.text:1000A59E   mov     ?g_ExecutableHeapHandle@@3PAXA, eax ; void * g_ExecutableHeapHandle
...

but ScyllaHide prefers to mark all heaps as non-executable:

if (ReadProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0))
{
  heapFlags &= HEAP_GROWABLE;
  WriteProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0);
}

and these 2 options kinda conflict with each other. πŸ™‚

Workaround & fix

This small bug can be used to detect ScyllaHide, as it's enabled by default in all configurations, and tooltip explicitly suggests to leave it as-is:

Very important option, a lot of protectors check for this value.

Here is a suggested patch:

if (ReadProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0))
{
  heapFlags &= (HEAP_GROWABLE | HEAP_CREATE_ENABLE_EXECUTE) ;
  WriteProcessMemory(hProcess, heapFlagsAddress, &heapFlags, sizeof(DWORD), 0);
}

If you don't want to recompile the entire Scylla, here's the binary patch for the official ScyllaHideOlly1.dll from ScyllaHide_v1.3fix_Olly1.rar package:

00005A0B: 85 81
00005A0C: C0 65
00005A0D: 74 FC
00005A0E: 14 02
00005A0F: 83 00
00005A10: 65 04
00005A11: FC 00
00005A12: 02 90

As a simple workaround, you could uncheck "HeapFlags" in ScyllaHide when debugging .NET applications. However, I would really suggest to fix ScyllaHide instead.

Have fun and keep it safe!

Fighting comment spam

kao

When I started this blog, I was aware that comment spam exists. What I didn't know, is how common it really is. πŸ™‚

Current statistics are:

Comment type Count %
Spam 39 56
Normal 29 41
Trashed 2 3
Total 70 100

What can be done?

WordPress has several anti-spam plugins. Some of the add captchas, some rely on JavaScript and others rely on continually updated blacklists for spammer IPs and/or keywords. I hate captchas, I respect users that use NoScript, and my webhost is running with allow_url_fopen = false which prevents automatic blacklist updates. Crap!

So, I'm left with a very few options, like blocking spammer IP address ranges using .htaccess file and mod_rewrite.

mod_rewrite magic

When you know what you're doing, mod_rewrite does wonders. When you don't, you might lock yourself out of web-admin interface. Trust me, it's not fun! πŸ˜‰

In the very simplest form, we can block one IP address:

RewriteCond %{REMOTE_ADDR} ^(123\.456\.789\.666)$
RewriteRule (.*) - [F,L]

First line is a condition - if visitor comes from IP address 123.456.789.666, then apply the rule. Keep in mind that mod_rewrite is matching IP address against regexp, so do not forget backslashes! Otherwise you might accidentally block more than you wanted..

Second line is the rule - whatever URL it tries to access, send response "403 Forbidden". (.*) is a regexp matching anything1. [F] forbids access and [L] stops any other rules from applying, making it the last rule.

It will work, but my webhost does not allow custom 403 pages. So, we can adjust the example a bit:

RewriteCond %{REMOTE_ADDR} ^(123\.456\.789\.666)$
RewriteCond %{REQUEST_URI} !/error.html$
RewriteRule (.*) /error.html [R=302,L]

Now there are 2 conditions, first is matching IP address, 2nd is checking if requested page is not error.html. Note that by default all conditions must match (logical "and").

Also, [R=302] is used to redirect users with Error 302 Found to error.html instead of sending Error 403 Forbidden.

It's better, but we need to block several IP blocks. That's easy too!

RewriteCond %{REMOTE_ADDR} ^123\.456\.789 [OR] RewriteCond %{REMOTE_ADDR} ^555\.666
RewriteCond %{REQUEST_URI} !/error.html$
RewriteRule (.*) /error.html [R=302,L]

Flags [OR] say we're checking if IP address begins with 123.456.789 or 555.666. Also, the regexp was changed to check only beginning of IP address, and ignore the rest.

That's it. Easy, right? πŸ™‚

Identifying spammer-friendly IP blocks

I just went through my inbox and looked at the "Please moderate" emails:

Author : Adrienne (IP: 104.168.70.107 , 104-168-70-107-host.colocrossing.com)
E-mail : hekhwrjjrab@mail.com
URL : http://Adrienne
Whois : http://whois.domaintools.com/104.168.70.107
Comment:
Hi, my name is Adrienne and I am the sales manager at {Spammer Company}. I was just looking at your When software is good enough | Life In Hex website and see...

So, the offending IP address is 104.168.70.107.

DomainTools tells us it's owned by ColoCrossing, and how large the IP block is:
IP Location: United States United States Williamsville Proxy R Us.com
ASN: United States AS36352 AS-COLOCROSSING - ColoCrossing (registered Dec 12, 2005)
Resolve Host: 104-168-70-107-host.colocrossing.com
Whois Server: whois.arin.net
IP Address: 104.168.70.107
NetRange: 104.168.0.0 - 104.168.127.255

Going through other notification emails, I identified 2 more spammer-friendly proxy/vps services: AS15003 and Krypt. It covers almost all comment spam, the rest are residental IP addresses in China and Vietnam - most likely part of some botnet and not really worth blacklisting.

Putting it all together

Armed with basic knowledge about mod_rewrite and offending IP addresses, I put it all together:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !/403.html$
RewriteCond %{REQUEST_URI} !/403.png$
RewriteCond %{REQUEST_URI} !/403.css$
RewriteCond %{REQUEST_URI} !/sad.png$
RewriteCond %{REMOTE_ADDR} ^23\.108\.170 [OR] RewriteCond %{REMOTE_ADDR} ^23\.94 [OR] RewriteCond %{REMOTE_ADDR} ^104\.168 [OR] RewriteCond %{REMOTE_ADDR} ^98\.126
RewriteRule (.*) /403.html [R=302,L] </IfModule>

So, anyone coming from those IP address blocks will get redirected to http://lifeinhex.com/403.html. Problem (hopefully) solved! πŸ™‚

Further reading

These sites were invaluable in adding simple spam block to my blog:
How to redirect requests from particular IP addresses or networks with mod_rewrite - basic usage.
System: mod_rewrite: Examples - great examples, explained well.
mod_rewrite Cheat Sheet - all I ever wanted to know, and little bit more.
How To Ban And Block Proxy Servers? - I didn't have to take this approach yet. And it wouldn't work against "elite" proxies anyway.

Footnotes

1. Actually, the pattern in the RewriteRule does not need to match the _whole_ URL, so you might encounter "$", "(.*)", "." and many more variations in these kinds of rules.

Miserable state of open source code

kao

Yesterday I wanted to make a small API hook detector in C#. It has to parse PE file, find exported functions, read bytes from the beginning of function and then compare them with the bytes in process memory. Sounds simple, right?

Well, good luck finding a PE parser that actually works!

Looking for PE parser

Most of PE parsers stop at parsing DOS header, NT headers and section headers. But I needed something that would also parse export table for me. After a couple of Google searches I ended up with PEReader by DKorablin. From the first look it's decent and even has a demo application. What else could you want?

Hmmm, how about working correctly on really simple files? πŸ˜‰

Sorry, nope.

Results from PEReader and CFF
It sure finds exported functions but it mismatches function names & RVAs. So, if you wanted to examine, say, CreateFileW, you will end up examining DeleteFileA. Or some other random API. Great job!

But it's opensource. Just fix it and submit a patch!

Umm, no. I was looking for a PE parser that I can take, load it in VS and use it. I don't want to spend days hunting down bugs and fixing them - this stops me from doing what I really want to do.

So, dear opensourcer, if you are publishing your code, make sure it actually works. If it doesn't work, please don't publish it at all - it's not helping anyone. Don't waste other people's time..

P.S. I ended up with using DNLib and writing my own PE export parsing. At least, I know it works properly..

Gigaom suspends operations

kao

This day started with some sad news:

Gigaom recently became unable to pay its creditors in full at this time. As a result, the company is working with its creditors that have rights to all of the company’s assets as their collateral. All operations have ceased.

Gigaom is (was?) a very nice technology site. I liked it. And I'll certainly be sad to see it go. However, this failure proves something I've said for years, yet everyone else seemed to disagree:

If your web-based business depends on ad revenue, you're going to fail.

Sure, some stay at home moms can get few hundreds of bucks per month by blogging about the color of their baby poop. And some other stay at home moms will read this shit blog, looks at the ads, and possibly even click on Pimpers(tm) picture to buy some. Yes, that can work.

But you can't build a real business based on ad revenue.

Nobody loves ads

Face it - people hate ads. That's why people install adblockers. It's not because they hate you, the poor publisher. It's not because adblocker speeds up web page loading time. And it's certainly not because people need to save some traffic.

You can remind them nicely:
flightradar

You can nag and deny access to your precious content, like ArsTechnica did in 2010, or lots of sites try to do today:
playindiafilms

But no matter how hard you try, you can't make a long-term business based on ads.

R.I.P. GigaOm, I hope others will learn from your failure.