I am an old-school Quicken user, back to the Apple II days. Intuit used to be OK, but as the Mac declined in the 90s, Intuit started ignoring it. Every year they would throw a few more features into Quicken that no one cared about, and everyone would upgrade.
Bank connectivity was simple; you downloaded files from your bank in the
QIF format, and you reconciled things. But QIF wasn't a great file format. There was an open file standard called
OFX that Microsoft Money used, but Intuit didn't see the appeal in that. Intuit took OFX, added a custom field to it called "INTU.BID", called the file format
QFX, and started charging banks to get a number to put into that field. And because Quicken now worked online, Intuit could
enforce the payment from banks. If banks didn't pay, Quicken wouldn't know about their "INTU.BID", and Quicken wouldn't download their customers' data.
I don't know if that's
legally extortion, but I'm going to call it that. And so do lots of other
unhappy people.
Meanwhile, Intuit continued to screw over Mac users. The last version of Quicken that Intuit released for the Mac was Quicken 2007. It was a PowerPC app. In 2009 they
announced a new app, "Quicken Essentials for the Mac", which was released in February of 2010. It was an under-powered joke that didn't do things like track investments, so Intuit suggested that people who needed to do more than balance their checkbook keep using Quicken 2007.
When Mac OS X Lion came out, and Quicken 2007 wouldn't run any more because it was a PowerPC app, Intuit acted swiftly. Lion came out in July of 2011, and
seven months later in March of 2012 Intuit released a crappy recompilation into x86.
And that's it.
Why do I bring this up? Because I
hate Intuit. I
despise them because they have made it abundantly clear that they despise me and all of their customers.
A few months ago, I signed up for the computer-driven investment manager
Wealthfront, started by people who wanted to use high tech to bring quality investing to non-finance minded people (e.g. me). (I think they're cool enough to recommend; I'd like it if you were to sign up with
my referral link so that both you and I save money, though it's your call and I won't mind it if you don't.)
But Wealthfront uses
Apex Clearing to hold their accounts, and while Apex paid their Intuit tax and offers QFX downloads, guess what? They paid for Windows but not Mac. And so Mac Quicken won't import their files.
Now, ever since Intuit pulled the INTU.BID stunt with QFX, people have been trying to work around it. If you google around, you'll find the usual suggestion is to
switch out the INTU.BID number for one that works. I tried that, but couldn't get it to work.
And then I asked myself, why don't I fix Quicken itself?
When you open an unauthorized QFX file, you get the "unable to verify the Financial Institution information" dialog. So I took a stack trace, and that dialog is fired from:
QApplication::OpenQuickenDoc(short, long, char*, unsigned long, long) + 225 [0x278b45]
QApplication::OpenWebConnectFile(short, long, char*) + 186 [0x278a34]
QMSession::ProcessWebConnectFile(char const*) + 306 [0x20e23e]
QMSession::SendSessions(short&, StretchyString&) + 2392 [0x20ec4c]
SessionMgr::StartLocalMsgSetSessions(unsigned short, EBVoidPtrArray*, SendQ*, short, unsigned long) + 180 [0x4813ca]
MsgSetConnectionMgr::CreateLocalSessions(unsigned short, EBVoidPtrArray*, SessionList*) + 1227 [0x3fe969]
QMSession::BeginMessageSet(unsigned short, OEMessageSetRs*, unsigned long, OEString const&) + 79 [0x20f19b]
QImportOFXRs::PrepareForSession(OEString const&) + 722 [0x212f6e]
DoErrorMsg(char*, char*, OpaqueWindowPtr*, AlertFunctor*) + 39 [0x38d7fc]
Note that they ship their binary with symbols. Really. This made my job a million times easier.
So I went to look at
QImportOFXRs::PrepareForSession. When I tossed Quicken into
Hopper and went to that function, I saw:
Look at the call to
EBCache::GetWebConnectInfoForFeature. Quicken tests to make sure it has web connect info, and if it doesn't have that info it throws up the error dialog and dies.
But what's interesting is that, at 212f73, it immediately overwrites
eax. In other words, Quicken tests to make sure it has web connect info for the bank, and then
immediately throws out that information. So what happens if I
NOP-out that entire error block, so that Quicken always proceeds?
It works. Quicken puts "FI needs update" as the bank name, but it allows you to proceed with the import.
There is a problem, though. I experimented a bit, and found that if you do a partial import, and then try to go back to the "Download Transactions..." window, Quicken will say that you need to update your bank list. And if you allow it to do so, it realizes the tricks you've pulled, and disables your account from ever importing again.
That particular dialog, the "you had an online account for a bank we don't know about any more, so we're going to disable it" one, comes from the stack trace:
OldQuickenMenuGlue::DoCommandProcess(PPx::SysCarbonEvent&, HICommand, unsigned long, unsigned long) + 156 [0x1b2610]
MenuManager::DoCommand(long) + 107 [0x1b1173]
OnlineMenuHandler::DoCommand(short) + 75 [0x1b5503]
needsToUpdateBankList() + 579 [0x1b5e07]
DoAlert(short, unsigned char const*, unsigned char const*, unsigned char const*, unsigned char const*, unsigned char const*, short, short, short, OpaqueWindowPtr*, AlertFunctor*) + 898 [0xd6d51]
DoAlert(short, __CFString const*, __CFString const*, __CFString const*, __CFString const*, __CFString const*, __CFString const*, __CFString const*, AlertButton, AlertButton, OpaqueWindowPtr*, AlertFunctor*) + 215 [0xd69c3]
Looking, it seems like
needsToUpdateBankList is a bad function to ever be in. No. We should never want to update the bank list.
Fortunately, that's easy.
I overwrote the first few bytes of the function with
33C0C3 which is
xor eax, eax; ret.
I don't know if I'm done. Who knows what other subtle pitfalls I might need to disarm that I don't yet know about? But I have a working import:
and right now that's all that matters.
(Note: All offsets are as of Quicken 2007 version 16.1.4 (build 23.880.400). Your mileage may vary. This will probably void your warranty and possibly your EULA. Please take the usual precautions, including backing up your original application binary.)