text:
Late last year he resurfaced and officially declared his candidacy for president.
The star of the Home Alone recently resurfaced with this bizarre video of him eating pizza.
The man who resigned as Prime Minister after just two weeks on the job had resurfaced.
He would quietly make certain that a bridge in Rockford got resurfaced with federal funds.
Two weeks later Ahmad resurfaced in a video posted to the Web, staring hollow-eyed at the camera in front of a bare concrete wall.
He resurfaced in a televised "confession" in mid-September where he retracted much of his criticism of the government.
Four decades of turmoil have devastated archaeological sites, but the chaos has also resurfaced previously buried treasures.
Subsequently, when the road was resurfaced with limestone, which was much softer than the trap, it became excellent.
Turning shoreward she dived and resurfaced approximately 300 feet in the opposite direction from which she was being pursued.
This erasing was done with a knife or pumice stone and when resurfaced by rubbing the vellum could be readily used a second time.


text:
Honeynet Project Scan of the Month - Scan 33 (November 2004)
Submission by Eloy Paris <peloy at chapus dot net>
Fri Dec 3 18:34:47 EST 2004
"I've seen things... things you little people wouldn't believe... Attack ships on fire off the shoulder of Orion bright as magnesium... I rode on the back decks of a blinker and watched c-beams glitter in the dark near the Tanhauser Gate. All those moments... they'll be gone." Roy Batty (Nexus 6. Incept date 2016)
This is a submission to the Honeynet Project's November 2004 Scan of the Month.
The analysis is in some parts very detailed. If you are a grader, have several submissions to read and can't go over all the details, or are just a casual reader, feel free to go directly to Section 1, "Questions", which contains the answers to all the questions of this challenge. The questions (and answers) provide a good summary of the most important aspects of this challenge. However, just reading the answers is not the best way to learn and understand some of the details nor the process I followed to analyze 0x90.exe, so I encourage you to read the whole submission.
Table of Contents
A: The following are the anti-reverse engineering traps and techniques that I found while analyzing 0x90.exe:
Pushing the limits of the Windows Portable Executable (PE) format by tampering with some fields in the PE and section header so disassemblers like IDA Pro and objdump don't have a chance. This technique can be defeated by loading the file in the disassembler as a binary object as opposed to a PE executable.
Use of no-operation blocks: these blocks consisted of big numbers of instructions that served no purpose other than to hide the real instructions. These blocks were everywhere and slowed the analysis.
Use of the RDTSC (read timestamp counter) instruction to measure the number of cycles needed to execute sections of code, and abort the program if it looked like it took too long to execute, maybe due to the presence of a debugger.
Heavy use of Windows' Structure Exception Handling infrastructure. In particular, 1) attempting to kill debuggers from within an exception handler by writing zeroes to the microprocessor's debugging registers (DR0, DR1, DR2, DR3, DR6 and DR7), and 2) changing program flow from within an exception handler by directly manipulating the value of the EIP register saved in the stack as part of the _CONTEXT structure (see winnt.h)
Heavy use of encryption in different sections of the binary. These sections are decrypted on the fly and in different stages, most of them right before the code in an encrypted zone is executed. The huge number of decryption areas represents also a problem to the reverse engineer - in one instance there are 175 encrypted blocks that are being decrypted from different sections of the binary.
Use of a virtual machine to decrypt/unpack some parts of the binary, and to perform the function the program was created for. This might be the most difficult barrier to analysis and reverse engineering of this binary.
Very twisted way of calling library functions from the Windows API: all calls to the Windows API are made from the same place. The call instruction that invokes the API functions is modified right before making the call so the wanted function is called.
Attempts to detect software breakpoints (int 0x3 - opcode 0xcc) at the entry point of Windows API functions and kill the debugger if one is found.
Details about all these techniques, including their impact on the reverse engineering process and how they can be neutralized can be found in Section 2.2, "Anti-Reverse Engineering Techniques and How to Defeat Them".
A: What sets this binary apart is the use of a virtual machine to do an important portion of the decryption/unpacking process. In fact, the same virtual machine that is used to unpack the binary at run time is also used to perform the actual work of the program. The use of this technique really raises the bar in terms of the resources (patience, skills, creativity and time) required to break the protection of the binary and to understand the purpose in life of the protected program.
More details about the "Brulez" virtual machine can be found in Section 2.3, " x86 Machine Code Becomes Microcode (a.k.a. "the Machine Within") ".
A: In my opinion, there is no "quick" way to analyze a program that uses virtual machines to prevent reverse engineering, especially if the virtual machine is unknown and designed specifically to prevent reverse engineering. I believe that to be able to break the protection of a program that uses virtual machines as a shield against reverse engineering, the virtual machines have to be reasonably well understood because the extra level of abstraction that the virtual machine provides requires added complexity and in particular a higher number of real machine instructions per virtual machine instruction.
Quickly analyzing a virtual machine (as opposed to a program that uses virtual machines) is also something that in my opinion is hard to accomplish mainly because it might not be evident that one is dealing with a virtual machine. Experience, as always, will help.
I discovered I was dealing with a virtual machine when I determined that the x86 machine code was following some kind of "script" that was being tracked by the ESI register. After statically (in the disassembler, as opposed to the debugger) following execution of this script for a few x86 instructions I noticed that the program was using a few jump tables that were indexed by bytes in this "script" pointed at by the ESI register. I also noticed that each time that a jump was made through this table, a certain region of memory was being modified. It did not take long to realize that the "script" I was following was just machine code for what I later called "the Brulez Virtual Machine", and that this region of memory being modified was actually reserved for registers of the virtual machine.
The Brulez virtual machine turned out to be very simple and to have a small instruction set. The virtual machine program that was embedded in the binary was also simple, which allowed me to reverse engineer it. However, there was no magic formula or silver bullet - it was a pretty manual process that I don't see an easy way to automate.
Something that would probably help is to have an IDA processor module for the virtual machine being reverse engineer, but this is actually a Catch-22 since you can't have a disassembler for a virtual machine you still do not understand.
A: The most valuable tool to analyze a binary armored with some of the protections against reverse engineering that I outlined in Section 1.3, " Q3: Provide a means to "quickly" analyze this uncommon feature. " is a good disassembler. The reason for this is that a heavily armored binary will try hard to kill a debugger and to prevent all attempts to get to the core program, so using a debugger is not the best option. Static code analysis with a disassembler, and especially an "interactive" disassembler like IDA, is, at least to me, the best option. A lot of tasks (like decryption of encrypted sections) could be performed from within the disassembler by using its C-like language.
A: The 0x90.exe executable does only one thing: to print a welcome message if the correct key has been provided by the user.
C:\tmp>0x90 Please Authenticate! C:\tmp>0x90 1D3NEAcN Welcome... Exploit for it doesn't matter 1.x Courtesy of Nicolas Brulez C:\tmp>
The program does absolutely nothing malicious and can be run without fears.
A: The binary is expecting a key or serial number that authenticates the user. The main indication that the program is expecting some kind of authentication from the user is that when the program is run the message "Please Authenticate!" is displayed, as can be seen in the output shown in Section 1.5, " Q5: Identify the purpose (fictitious or not) of the binary. ".
The binary looks for this key in the command line, and there are two possible ways to realize this: the first one is by observing that the Imports Table of 0x90.exe includes an entry for the Windows API function GetCommandLine() (this does not mean much, though, since it could be a reverse engineering trick.) The second way, and the only one that is 100% guaranteed to be effective is to fully reverse engineer the binary and understand where it is looking for the authentication information. This is the approach that I took, and it has the added benefit that it allows to reverse engineer the key or serial format so the program can be run without patching it.
There are four possible keys that the program will accept. These keys are (not including the quotes):
To come up with these keys I had to fully understand the Brulez Virtual Machine program embedded in 0x90.exe. This VM program was the one actually checking the validity of the key. Basically, I had to understand what operations were being performed on the key, come up with a set of constraints a key has to satisfy, and then work backwards. The details about this procedure are too lengthy for this section of the report so please refer to Section 2.5, "Discovering Authentication Keys" for full details.
A: These are a few things that can be implemented to increase the time and skills required to break the protection of 0x90.exe:
Get rid of the pusha/popa instructions that enclose no-operation zones. This way it will not be trivial to identify no-operation zones so they can be hidden. Registers could be saved in the stack one by one, or in a special memory area, or only those registers modified by the no-operation zone instructions could be saved.
Get rid of the markers (the 0xdead and 0x31000) that are used to identify each decryption block. Having these markers in there makes it just to easy to automatically decrypt the section of the binary the markers deal with. Each decryption block in the chain should be different so finding a pattern is very hard to do. The idea would be to create a tool that makes creation of the decryption blocks very easy, but that makes identification of them very hard.
Monitor changes in the debugging registers: if during execution the program checks for the value of the debugging registers at two different point and it finds that some values have changed that means someone is messing around with a debugger and the program should bail out.
Implement a more complicated virtual machine: more instructions are needed. Also, the current implementation of the instruction decoder via tables is too easy to figure out. A more manual process should be implemented and decoding of virtual machine instructions should be obfuscated.
Use a virtual machine and write no-operation zones in the virtual machine program. This would keep the reverse engineer busy for a while.
The entire real program could be run in a virtual machine, as opposed to just parts of it. I dread a program written in a high level language like Visual Basic because one high-level language constructs translates into lots of low-level language instructions and unintelligible library calls. So, a high level language can be seen as a virtual machine.
Detect machine virtualization software like VMware since chances are that if someone is running the binary in a virtual machine that user is trying to reverse engineer it.
Use of strong encryption: this is one that would be impossible to break. If the binary were encrypted and only a way-one password could decrypt it then it would be impossible to reverse engineer the program unless it could be caught decrypted in memory while running.
Note that these are just some examples of anti-reverse engineering techniques and that none of them is a silver bullet (except maybe the last one above, encryption) - anyone with sufficient determination will always find a way to break the protection.
What follows is a comprehensive analysis of the 0x90.exe binary.
The 0x90.exe is a Win32 console application. The objdump from the binutils package helped me to get an initial idea of what I was dealing with.
During the initial and very superficial inspection there are two things that I noticed immediately: first, that the strings command is useless. Running this command only gives us the following "useful" information:
(You really thought you would find strings eh? ;-) Scan of the month coded by Nicolas Brulez / Digital River
This is to be expected, though, since these days 99.9% of malware is packed with some kind of executable packer for two reasons: 1) to prevent the casual user from finding useful information (like the FQDN of an IRC server hosting a botnet), and 2) to minimize the size of the executable.
The second thing that I noticed was that objdump, IDA Pro, and other tools to explore PE files fail miserable to disassemble the binary or to obtain some information about it. As I will show, the reason for this is that the section headers, and the PE header in general, have been tampered with to cause troubles.
Finally, as part of a very superficial and initial analysis, I always like to run the malware to try to obtain as much information as possible about its purpose. Needless to say, running malware is dangerous, and must be done in a sandbox in an air-gapped network and in a machine that can be quickly restored to the state prior to running the malware. I usually use a VMware virtual machine, which does not always work due to the fact that today's malware attempts to detect whether it is running on a virtual machine. So, having said this, I ran the malware and got the following output:
C:\tmp>0x90 Please Authenticate!
It is important to note that running the malware several times in short succession will cause it to apparently hang or not produce any output at all some times. I will speculate on the reason for this behavior later on.
After a short initial and superficial inspection I proceeded to use the real tools that could potentially help to get this job done: a disassembler and a debugger. Using these tools I encountered a good number of anti-reverse engineering traps of various level of complexity. In this section I will present the traps I found, what their impact was, and how I managed to evade or neutralize them.
What: As I mentioned in Section 2.1, "Initial Inspection", the 0x90.exe program could not be loaded in a disassembler as a Windows PE executable. The reason for this is some non-sense values in the PE header and section header. These non-sense values obviously do not stop the Windows executable loader for some reason.
Impact on Reverse Engineering: Not being able to disassemble the program you are trying to reverse engineer is a big problem. You can always resort to the debugger, but for really complicated tasks, a debugger alone is not enough: for heavily armored and powerful binaries, powerful reverse engineering tools are called for, so being able to load the file in a disassembler is a must.
Solution: I was short on time so I did not even look at the PE and section headers to see what Nicolas Brulez had done to them. I just loaded the file in IDA Pro using the binary loader (as opposed to the PE loader that was not getting me anywhere.) When using the binary loader I did load the program at offset 0xde0000, which is the image base reported by objdump. objdump also reported the program's entry point (at 0xde2000), so I was set to start analyzing the program.
What: The first thing that I found as soon as I started to trace through 0x90.exe in a debugger (or while looking at the disassembly) was that there were lots of instructions. This by itself is not a problem because programs, after all, are made out of instructions, but when you realize that these instructions are doing nothing then this might represent a problem. These no-operation instructions appeared always in blocks enclosed by a pair of pusha/popa instructions. Here's a short example of one of them:
seg000:00DE2012 pusha seg000:00DE2013 mov al, bl seg000:00DE2015 db 65h, 36h seg000:00DE2015 rep mov ecx, edx seg000:00DE201A repne jmp short loc_DE201E seg000:00DE201D db 0ABh seg000:00DE201E seg000:00DE201E loc_DE201E: ; CODE XREF: seg000:00DE201A seg000:00DE201E mov esi, esi seg000:00DE2020 db 26h seg000:00DE2020 repne lea ebx, es:0D0E47C6Eh seg000:00DE2028 db 65h, 64h seg000:00DE2028 repne mov ah, 51h ; 'Q' seg000:00DE202E jmp short loc_DE2031 seg000:00DE2030 db 27h ; ' seg000:00DE2031 loc_DE2031: ; CODE XREF: seg000:00DE202E seg000:00DE2031 db 2Eh seg000:00DE2031 mov al, ch [...] seg000:00DE227F db 65h seg000:00DE227F mov dh, al seg000:00DE2282 mov ecx, 7D30653Fh seg000:00DE2288 popa
Note how the code inside this no-operation block is meaningless, especially because 1) nothing is ever written to memory, and 2) only registers are affected, but the block begins with a pusha instruction and ends with a popa instruction, which destroys anything loaded into the registers within the block. Also, note how instruction prefixes like cs:, ds:, repe, repne, are being used for instructions that do not need them. For example, a "mov al, ch" instruction does not need a "repe" prefix, this does not make any sense since this prefix is used by string operations (scansb, movsb, etc.) I am surprised that the processor doesn't produce an illegal instruction trap or something, but it apparently can take all this crap.
Impact on Reverse Engineering: These no-operation blocks are everywhere and their impact is to tremendously slow down the reverse engineering process. In a disassembler is not that big of a problem because I can search for the closing popa of the block, but in a debugger it causes more problems.
Solution: Since this no-operation blocks are very easy to recognize it is possible to filter them out in the disassembler. One way of doing this is to identify most occurrences of these blocks and then tell the disassembler to hide these portions of code. To identify these portions of code I generated a listing of the disassembly and then used the Unix grep in the following way:
grep 'pusha\|popa' listing.lst > addresses.txt
This gave me a file with the beginning and ending addresses of the no-operation blocks. With this file I then created a small IDC program that just read this input file and then told the debugger to hide all this blocks. The addresses.txt was not perfect but it was a good starting point to hide all these blocks that were just slowing me down.
Here's how the above code segment looks after hiding all the no-operation zones (note the "no-operation zone" comments and how many bytes of sequential memory they cover):
seg000:00DE2009 sub eax, 6 seg000:00DE200C sub ebp, 0DE2006h seg000:00DE2012 ; no-operation zone seg000:00DE2289 ; no-operation zone seg000:00DE22F1 ; no-operation zone seg000:00DE259A seg000:00DE259B ; no-operation zone seg000:00DE2603 mov [ebp+0E26441h], eax seg000:00DE2609 ; no-operation zone seg000:00DE2671 ; no-operation zone seg000:00DE2950 mov eax, 0DE100Dh seg000:00DE2955 ; no-operation zone seg000:00DE2C2C mov eax, [eax+2] seg000:00DE2C2F ; no-operation zone seg000:00DE2EF1 mov eax, [eax] seg000:00DE2EF3 ; no-operation zone seg000:00DE2F5B mov edi, eax seg000:00DE2F5D mov ecx, 4
What: It was common to see code like the following:
seg000:00DE22B9 cpuid seg000:00DE22BB rdtsc seg000:00DE22BD sub eax, [esp] seg000:00DE22C0 add esp, 4 seg000:00DE22C3 cmp eax, 0E0000h seg000:00DE22C8 ja short loc_DE22CD seg000:00DE22CA xor eax, eax seg000:00DE22CC retn seg000:00DE22CD loc_DE22CD: seg000:00DE22CD add dword ptr [ecx+0B8h], 63h ; 'c' seg000:00DE22D4 xor eax, eax seg000:00DE22D6 retn
This code is basically using the rdtsc instruction to measure the number of cycles that it takes to execute a section of code. This information is then used to kill the program if it is detected that too many cycles have passed (0xe0000 in this case.) The program is being killed by adding some random junk to the saved EIP register (this particular code is being executed inside an exception handler.)
Impact on Reverse Engineering: This does not affect the reverse engineering process when analyzing code in the disassembler but can potentially cause problems in the debugger if one is not careful and steps through this code.
Solution: If stepping through code in the debugger just skip over this code by changing the value of the EIP register.
This rdtsc non-sense is what is causing the program to behave erratically (see last paragraph of Section 2.1, "Initial Inspection") since it gives false positives ("positive" here meaning "you took too long to execute this, just must be stepping through code in a debugger") that then hang the program based on the decision it makes when a positive is detected.
What: The program is taking advantage of Windows' Structure Exception Handling infrastructure to wreck havoc. Basically, the program sets exception handlers at lots of different places in the program and then generates an exception (trying to dereference a NULL pointer.) The exception handler then takes control and does some nasty things. In particular, different types of exception handlers were : 1) trying to kill the debugger from within an exception handler by writing zeroes to the microprocessor's debugging registers (DR0, DR1, DR2, DR3, DR6 and DR7), and 2) changing program flow from within the exception handler by directly manipulating the value of the EIP register saved in the stack as part of the context structure.
Impact on Reverse Engineering: The user of Windows SEH infrastructure is a major problem - it basically make it impossible to debug the program.
Solution: Solving this problem is tricky. The solution that I implemented was to find all the places with exception handlers and patch them so they are not executed. For those exception handlers that were changing program flow I just changed the program flow from within the main program by putting in place jumps to the final destination. The actual patching was done by a small C program (decrypt-0x90.c) that I wrote, although it could have been done easily in IDA's IDC language.
The way to use decrypt-0x90.c is as follow: you run it a give as command-line argument the name of the 0x90.exe you want it to patch for you. This file will be patched and then you can use that to run in the debugger without fearing the exception handlers. You can also load this file in the disassembler and analyze that one instead of the original 0x90.exe. I used both techniques.
What: Hundreds of sections of the binary were "encrypted". They were "encrypted" with single XOR operations, but encrypted nonetheless. The problem was not the encryption method itself, because both the keys used to encrypt and the sections within the file that were encrypted were easy to find. The problem was the big number of these encrypted sections.
It is interesting to delve into the details of how all the encrypted sections of the binary were organized:
The first encryption section was what I call a "chain" of 173 encrypted blocks. Each one of this blocks had the following structure (taking from the C program I wrote to decrypt them):
struct decryption_block { char decrypt_code[155]; char nop_code[8]; char get_size_code[13]; char get_addr_code[14]; unsigned marker1; /* 0xdead */ unsigned code_offsets[4]; unsigned marker2; /* 0x31000 */ unsigned return_offsets[4]; } __attribute__((packed));
All blocks had the same structure. The first four arrays are used to account for x86 code that performs four functions: do the actual decryption, do nothing, get the size of the code to decrypt and get the starting address of the block to decrypt. marker1 is a constant marker that is always the 32-bit word 0xdead (yeah, no comment here). Following that are the offsets, from the image base, to the four functions described above. marker2 is another marker that is always 0x31000. Following that marker there are four 32-bit words that are used to calculate the return address from the four functions described above. Functions are called in the following order: get address, do nothing, get size of block to decrypt, and decrypt. The decryption code is very simple and always the same:
void decrypt(char *buffer, unsigned size) { do { *buffer++ ^= size; } while (--size); }
This first chain had a total of 173 of these decryption blocks. They were located at the very top of the binary, i.e. higher memory addresses, with the first block in the chain at higher memory addresses with each subsequent block at lower memory addresses. Each decryption blocked was responsible for decrypting the code that was going to be executed next.
After the first chain, there was a second chain, and a different address (that's why I call this a different chain). This one only had two decryption blocks, but they had the same structure I presented above.
Impact on Reverse Engineering: These hundreds of encrypted sections made it impractical to use a debugger for several reasons. First, I could not just set a breakpoint at the end of all decryption blocks because I did not know where the encrypted blocks were going to end. Second, because the exception handlers I presented above would have killed the debugger. Third, because, as I later found out, the decryption blocks were so many that stepping through all of them would have been impractical. In addition to the inability to efficiently use a debugger to go through the decryption process, another impact of the heavy use of encryption in this binary on the reverse engineer is that the file is very hard to analyze, even statically in a disassembler. The reason for this is that there isn't a single subroutine that decrypts the entire file, all sections. Instead, decryption was done in very different places, and each time something got decrypted it was to execute it next.
Solution: Solving this problem is also tricky. The solution that I implemented was to find all the places with exception handlers and patch them so they are not executed. For those exception handlers that were changing program flow (the ones inside the virtual machine microcode) put in place jumps to the final destination (the same thing that the actual exception handler had done if an exception had occurred.) The actual patching was done by the same (decrypt-0x90.c) that I described above in Section 2.2.4, " Heavy Use of Windows' Structured Exception Handling Infrastructure ". Again, this could have been accomplished without leaving IDA through IDA's IDC language.
decrypt-0x90.c decrypted the first two chains by traversing the decryption block structures in high memory. It did this by starting with the first one and keep going while the 0xdead and 0x31000 markers were in place; something like (important thing to see here is the for() loop):
#define MARKER1 0xdead #define MARKER2 0x31000 void decrypt_chain(struct decryption_block *d, char *buffer) { unsigned decrypt_len, decrypt_addr; for (;d->marker1 == MARKER1 && d->marker2 == MARKER2; d--) { decrypt_len = *(unsigned *) &d->get_size_code[1]; decrypt_addr = *(unsigned *) &d->get_addr_code[2]; decrypt(decrypt_addr, decrypt_len); } }
Once the two encryption chains have been decrypted I can patch the program to just jump over them, skipping all this mess. I can also use the resulting new binary as the new starting point of our disassembly, which is what I did.
As I will show next, after the two encryption chains were defeated I found a bigger challenge: what I call the "Brulez Virtual Machine". I will go into detail about this virtual machine in the next section but here I just want to point out that the virtual machine program performed decryption of two additional encrypted sections (one section was unconditionally decrypted, the last one only if the user authenticated correctly.) The first decryption performed by the virtual machine was an XOR with 0x53. The second decryption was an XOR with 0x43.
It is important to note that the final approach I used to neutralized most of the encryption was not the first one I tried. Just to give an idea of the wrong approach I originally was following, I was going through the first encrypted sections and learned quickly how to neutralize some of the reverse engineering techniques I have mentioned and that were being employed during the decryption process (no-operation blocks, exception handlers). I managed to get the program under a debugger to decrypt a section. Then I kept going and found another encrypted section. I decrypted that one, continued, and found another encrypted section. I decrypted that one too and continued hoping that it was the last one. I kept going for a few more sections until I realized that depending on the real number of encrypted sections I could be spending an unreasonable amount of time going through the encrypted sections manually so I decided to try a different approach.
What: After defeating the two decryption chains I presented in detail in the previous section I found a worthier challenge in the code that followed the last decryption block of the last chain: a virtual machine that was responsible, through a program written in this virtual machine's machine code, for the decryption of additional sections of the binary, for user authentication, and for performing the actual task the program was created for, i.e. executing printf("Welcome").
Impact on Reverse Engineering: The impact of a virtual machine and the corresponding virtual machine program embedded in a program has a huge impact on a reverse engineering task. I have seen challenges like this when trying to reverse engineer programs written in very high level languages, especially interpreted languages, which can be seen as "virtual machines". The problem is that it is very difficult to follow what the program is doing, neither statically in a disassembler, nor dynamically in a debugger, because the program one is trying to understand becomes microcode for the higher level instructions of the virtual machine. So, one virtual machine instruction takes several host machine (in this case the x86 machine) instructions to complete. In addition, the virtual machine has to deal with decoding of the instructions of the virtual machine, which causes additional complexity and pain to the reverse engineer.
Solution: Once I realized that it was a virtual machine I was dealing with, and that there was virtual machine code embedded in the binary it was just a matter of reverse engineering the virtual machine, understanding this machine's instruction set, and finally understanding the embedded virtual machine program. This understanding of the virtual machine program is what finally allowed to break the binary and understand its purpose.
What: The 0x90.exe binary has a very peculiar way of calling functions from the Windows API, at least in the most sensitive places of the program (inside the virtual machine program): instead of using regular call that goes through the Import Address Table (IAT) to reach Windows API functions, the binary goes to the IAT, fetches the address of the Windows API function that is going to be called, modifies the operand of a call instruction based on what was fetched from the IAT, and then executes the call. This is a very twisted way of calling functions in the Windows API.
Impact on Reverse Engineering: This trick has a low impact on the reverse engineering process. The impact is higher is the reverser is using a debugger and setting breakpoints at the entry points of the Windows API functions: in this case the reverser will see that all calls to the Windows API will come from the same place in the program, which is very confusing. The impact on the reverse engineering process is very low if analysis of the program is being done statically in the disassembler.
Solution: I was not affected by this trick since by the time I encountered this technique I had already understood the instruction set of the virtual machine, which is where the calls to the Windows API are being made (GetCmdLine() and printf().
What: In lots of different places 0x90.exe tries to kill the debugger, or more accurately, the program if it is determined that it is running under a debugger. Some ways the program or debugger is killed if it is determined that it is running under a debugger are: 1) by writing zeroes to the processor's breakpoint-address registers (DR0 through DR3), to the debug status register (DR6) and to the debug control register (DR7) from within all the exception handlers and 2) by jumping to a random address (the output from the RDTSC instruction, actually) in those instances when a debugger has been detected.
If I remember correctly there is only one instance where a debugger is explicitly searched for: at the very beginning of the program the first four bytes at the entry point of three Windows API function calls (GetCmdLine(), printf(), and ExitProcess() ) is searched for the presence of the byte 0xcc, which is corresponds to the instruction "int 3", and that is used to enter a debugger from a program. The code that does this search gets to the entry point of the API function by going through the IAT. Here's an example of this code. See how if a 0xcc byte is found the program jumps to a random address:
seg000:00DE3274 mov eax, 0DE1001h seg000:00DE3279 ; no-operation zone seg000:00DE3555 seg000:00DE3558 mov eax, [eax+2] seg000:00DE355B mov eax, [eax] seg000:00DE355D ; no-operation zone seg000:00DE37F1 mov edi, eax seg000:00DE37F3 ; no-operation zone seg000:00DE3A8F seg000:00DE3A90 mov ecx, 4 seg000:00DE3A95 mov eax, 660h seg000:00DE3A9A shr eax, 3 ; eax == 0xcc here seg000:00DE3A9D ; no-operation zone seg000:00DE3D2E seg000:00DE3D2F repne scasb seg000:00DE3D31 test ecx, ecx seg000:00DE3D33 jz short loc_DE3D39 seg000:00DE3D35 rdtsc seg000:00DE3D37 push eax seg000:00DE3D38 retn
Impact on Reverse Engineering: This anti-reverse engineering trick can be a real problem if one is not careful. One should prevent the debugging registers from being written to by anything that is not the debugger or control of the debugger will be lost and bad things will happen. This trick is not an issue, however, if static analysis in a disassembler is being performed.
Solution: This anti-reverse engineering measure is easy to prevent: just skip the section of code that is trying to mess up with the debugging registers or that is trying to find a debugger by looking at software breakpoints. One can also use hardware breakpoints, which don't require inserting a 0xcc into the program to cause a debugger trap.
In the previous section I mentioned that one of the biggest anti-reverse engineering mechanisms used in 0x90.exe is the use of what I call "the Brulez virtual machine". In this section I will go in more detail about how I discovered the virtual machine, what it is, how it works, and what it does.
At some point during the execution of 0x90.exe the register ESI was loaded with a certain memory address. The way the ESI register started to be used after that point caught my attention. It caught my attention because execution of the program started to be dependant on the value of the first two bytes at the address ESI was pointing at. These two bytes were always used as indexes into two of several jump tables, and the value of ESI would always change after performing a certain task. It seemed like the data pointed at by ESI was some kind of script that was controlling execution of the program.
So, I noticed the strange behavior but I did not make the connection immediately. Instead, I manually followed execution of 0x90.exe on paper/disassembler (not debugger), taking notes of the values of key registers and memory locations modified by the segments of code reached through the jump tables. The code reached through the jump tables seemed to be doing very specific and short tasks, like push a number to the stack, XOR a byte in memory with the contents of a register, etc. Then, the code would increment ESI by a short number (3, 5, 6, 7 - always depending on the value of the first two bytes pointed at by ESI) and another jump through the same tables would be performed.
If I remember correctly, it was after the ESI register went back to a value I had already seen that I said "oh my Gosh, there is a virtual machine here!". I then realized what I was dealing with and that the memory area pointed at by ESI was actually machine code for a virtual machine that I immediately called "Brulez" for obvious reasons. The next steps for were then to understand the instruction set of this new "microprocessor" so I could understand what the virtual machine program was doing. This is what allowed me to finally defeat the program.
The Brulez virtual machine has a very simple yet powerful enough (for the purposes it was designed) architecture. The processor has five 32-bit general purpose registers, named r0 through r4, and one flag register called nz (non-zero), which only holds two values: 1 if the result of a previous operation was non-zero, or zero if the result of a previous operation was zero. There is not a separate stack pointer (SP) register since the stack of the virtual machine is shared with the stack of the host processor. The host machine's ESI register acts as the Brulez virtual machine program counter (PC) register. Words are stored in memory in little endian byte order.
Brulez virtual machine instructions act on zero or more operands. Some operands are specified explicitly and other are implicit. The data for a source operand can be located in the instruction itself (an immediate operand), a register or a memory location.
Immediate Operands: some instructions use data that is encoded in the instruction itself as a source operand.
Register Operands: source and destination operands can be any of the general purpose registers r0 through r4.
Memory Operands: source and destination operands in memory are always referenced by an address stored in a general purpose register.
The instruction set of the Brulez virtual machine is pretty basic, but enough to accomplish the two tasks the virtual machine needs to: authenticate the user, decrypt two more sections of the binary, and print to standard output a message to indicate success or failure. Here I will list the instructions part of the instruction set classified by categories. In Appendix A, The Brulez Virtual Machine Instruction Set I present the entire instruction set listing opcodes and a short description for each instruction.
Data Transfer Instructions: ld (load), ldi (load immediate), ldbze (load byte zero extend), ldhze (load half-word zero extend), push, pushi (push immediate), pushi2 (push immediate 2), pop, clr (clear)
Arithmetic Instructions: add, addi (add immediate), subi (substract immediate), inc (increment), dec (decrement), ldc (load and compare)
Logical Instructions: xor, xori (xor immediate), ori (or immediate), andi (and immediate)
Control Transfer Instructions: call, ret (return), jmp, jnz (jump if not zero), jz (jump if zero)
String Instructions: strnchr (string character)
Bit and Byte Instructions: bswp (byte swap)
Miscellaneous Instructions: pcbe (pop, compare, and branch if equal), sys (system call), hlt (halt), trap (debugger trap), adjsp (adjust stack pointer)
The microcode (x86 machine code) of the Brulez virtual machine decodes instructions via data and jump tables. There is one data table for the first opcode of an instruction that contains the addresses of different data/jump tables. The second byte of the opcode is the used as an index into this second data/jump table. In one particular case (the xor instruction), there is a third table that is used to index based on the size of the operand (byte, half-word, and word.) Here is how these tables look like:
seg000:00E1B991 l1_jump_table dd offset off_E1B9A9 seg000:00E1B995 dd offset off_E1B9BD seg000:00E1B999 dd offset off_E1B9F5 seg000:00E1B99D dd offset off_E1BA25 seg000:00E1B9A1 dd offset off_E1BA29 seg000:00E1B9A5 dd offset off_E1BA35 seg000:00E1B9A9 ; seg000:00E1B9A9 ; level 2 jump table seg000:00E1B9A9 ; seg000:00E1B9A9 off_E1B9A9 dd offset pushi2 seg000:00E1B9AD dd offset pushi seg000:00E1B9B1 dd offset pushr seg000:00E1B9B5 dd offset pop seg000:00E1B9B9 dd offset adjsp seg000:00E1B9BD ; seg000:00E1B9BD off_E1B9BD dd offset loc_DF1A7B seg000:00E1B9C1 dd offset sub_DF442E+1 seg000:00E1B9C5 dd offset loc_DF59D2 seg000:00E1B9C9 dd offset xor seg000:00E1B9CD dd offset addi seg000:00E1B9D1 dd offset subi seg000:00E1B9D5 dd offset andi seg000:00E1B9D9 dd offset ori seg000:00E1B9DD dd offset xori seg000:00E1B9E1 dd offset add seg000:00E1B9E5 dd offset ldc seg000:00E1B9E9 ; seg000:00E1B9E9 ; this little table is used by the XOR instruction seg000:00E1B9E9 ; seg000:00E1B9E9 off_E1B9E9 dd offset xorb seg000:00E1B9ED dd offset xorh seg000:00E1B9F1 dd offset xorw seg000:00E1B9F5 ; seg000:00E1B9F5 off_E1B9F5 dd offset hlt seg000:00E1B9F9 dd offset sys seg000:00E1B9FD dd offset ldi seg000:00E1BA01 dd offset dec seg000:00E1BA05 dd offset inc seg000:00E1BA09 dd offset clr seg000:00E1BA0D dd offset strnchr seg000:00E1BA11 dd offset trap seg000:00E1BA15 dd offset ldmem seg000:00E1BA19 dd offset bswap seg000:00E1BA1D dd offset ldbze seg000:00E1BA21 dd offset ldhze seg000:00E1BA25 ; seg000:00E1BA25 off_E1BA25 dd offset pcbe seg000:00E1BA29 ; seg000:00E1BA29 off_E1BA29 dd offset jmp seg000:00E1BA2D dd offset jnz seg000:00E1BA31 dd offset jz seg000:00E1BA35 ; seg000:00E1BA35 off_E1BA35 dd offset call seg000:00E1BA39 dd offset ret
There is no provision for handling invalid instructions - an invalid opcode will just hang the virtual machine.
Since 0x90.exe has an embedded virtual machine it is obvious that there is also an embedded virtual machine program. I have mentioned in previous sections what this virtual machine program does, but in this section I go into the details of how the program works and what it does. Let's start by showing the program, and then I'll explain the purpose of some blocks of code:
1 .org 0xe1ba3d 2 3 ldi r3, 0x20e 4 pushi 0xe1ba65 5 pop r0 6 ldi r2, 0x53 7 ; 0xe1ba54 8 loop1: 9 xor.b (r0), r2 10 inc r0 11 dec r3 12 jnz loop1 ; 0xe1ba54 13 14 ; 15 ; Beginning of encrypted data 16 ; 17 ldi r1, 0x5cc80e31 18 sys GetCmdLine 19 strnchr ' ', 0x55 20 jz bad_key ; 0xe1bb6f 21 ld r2, (r0) 22 addi r2, 0x1d9bdc45 23 addi r1, 0x74519745 24 subi r2, 0xad45dfe2 25 addi r1, 0xdeadbeef 26 addi r2, 0x68656c6c 27 subi r1, 0x17854165 28 subi r2, 0x41776169 29 addi r1, 0x73686f77 30 addi r2, 0x69747320 31 subi r1, 0x206e6f20 32 addi r2, 0x64726976 33 addi r1, 0x6d657263 34 subi r2, 0x6e757473 35 subi r1, 0x79212121 36 subi r2, 0x65683f21 37 andi r2, 0xdfffffff 38 push r2 39 push r1 40 pcbe key_okay_1 41 ; tough luck, wrong key 42 clr r3 43 jz bad_key ; 0xe1bb6f 44 45 ; 0xe1bb06 46 key_okay_1: 47 inc r0 48 addi r0, 2 49 inc r0 50 ldhze r1, (r0) 51 push r1 52 pop r2 53 push r0 54 pushi 0xd8360d 55 pop r0 56 addi r0, 0x98548 57 dec r0 58 xor.h (r0), r2 59 pop r0 60 ldbze r2, (r0) 61 addi r0, 2 62 ldbze r1, (r0) 63 add r2, r1 64 call 0xe1bb86 65 66 ; The following instruction had the first byte "encrypted" 67 inc r3 ; r3 is 0 before execution of this instr. 68 push r3 69 pushi welcome ; 0xe1bc2a 70 sys printf 71 adjsp 8 72 jmp exit_vm ; 0xe1bb84 73 74 ; 0xe1bb6f 75 bad_key: 76 pushi2 0 77 pushi authenticate ; 0xe1bc13 78 sys printf 79 adjsp 8 80 81 ; 0xe1bb84 82 exit_vm: 83 hlt 84 85 ; subroutine 0xe1bb86 86 87 ldi r1, 0x4c 88 inc r1 89 inc r1 90 addi r1, 5 91 dec r1 92 subi r1, 4 93 subi r2, 0x5a 94 ldc r1, r2 95 ; tough luck - first part of key is correct but 96 ; second part is not 97 jnz bad_key ; 0xe1bb6f 98 99 dec r0 100 ldbze r2, (r0) 101 addi r0, 2 102 ldbze r1, (r0) 103 add r2, r1 104 inc r2 105 subi r2, 0x4e 106 pushi 0xe0dd64 107 pop r0 108 addi r0, 0xdeac 109 inc r0 110 xor.b (r0), r2 111 ldi r3, 0x49 112 pushi 0xe1bc2a 113 pop r0 114 inc r2 115 116 ; 0xe1bc00 117 loop2: xor.b (r0), r2 118 inc r0 119 dec r3 120 jnz loop2 ; to 0xe1bc00 121 122 ret 123 124 authenticate db 'Please Authenticate!', 0Ah, 0Dh, 0 125 126 welcome db 'Welcome...',0Ah, 0Dh 127 db 'Exploit for it doesn',27h,'t matter 1.x Courtesy of' 128 db ' Nicolas Brulez',0
From lines 3 to 12, the virtual machine program is decrypting 0x20e bytes starting at address 0xe1ba65. The decryption is a simple XOR of each byte with 0x53. Please note that the program above has already been decrypted to show what the program does.
From lines 18 to 20 the program call the Windows API function GetCmdLine() and searches for the first space (' ') in it. If no space if found then the program jumps to the label bad_key in line 75 where the message "Please authenticate!" is printed out and the virtual machine exits by executing a hlt instruction.
Note that the program is looking for the first space in the command line, which depending on what directory the program is being run from, and the name of that directory, the program might mistakenly look in part of the directory name for the key. For example, if the program is stored as C:\Documents and Settings\username\Desktop\0x90.exe and it is being run using the full path then the virtual machine program will think that the arguments to the program will start at the word "and" because that is the word that follows the first space. This is because GetCmdLine() returns the program name (including directory it is run from) plus the program's arguments. So, this opens some interesting possibilities, like:
From lines 21 to 40 the program performs the first check of the key. This checks just deals with the first four bytes of the first argument to the program. If the first part of the key is valid then executing continues in line 46 at the label key_okay_1. Otherwise the program jumps to bad_key.
From lines 50 to 58 the program reads bytes 4 and 5 of the first argument to the program and XORs byte 5 with the byte at line 67. This is to decrypt the instruction that lives there, which was encrypted.
Lines 60 to 64 load bytes 6 and 7 of the first argument to the program, add them leaving them in register r2 and call the subroutine at 0xe1bb86.
The subroutine performs the second and last check of the key and jumps to the label bad_key is the check is not passed. Otherwise it will decrypt the ret instruction at the end of the subroutine by XORing the byte at line 122 with 0x42, decrypt the data at line 126 (the string "Welcome..."), and return.
Finally, at line 67 the program prints the string "Welcome... Exploit for it doesn't matter..." by calling the library function printf() and the execution of the virtual program ends by calling the hlt instruction.
You have seen that the program authenticates the user by looking at the command line. In this section I will explain how to find the keys that the program will accept as valid.
As I mentioned in Section 2.3, " x86 Machine Code Becomes Microcode (a.k.a. "the Machine Within") ", in lines 21 to 40 the virtual machine program is checking the first four characters of the first argument to the program. In line 40 there is a comparison. Let's see what it is comparing: in one hand I have (0x5cc80e31 + 0x74519745 + 0xdeadbeef - 0x17854165 + 0x73686f77 - 0x206e6f20 + 0x6d657263 - 0x79212121) = 0xdf807499.
In the other hand the program is performing the following operation: (<first four characters of first arg to program> + 0x1d9bdc45 - 0xad45dfe2 + 0x68656c6c - 0x41776169 + 0x69747320 + 0x64726976 - 0x6e757473 - 0x65683f21) & 0xdfffffff. The result of this operation will be compared with 0xdf807499 (see previous paragraph) and if the two numbers are not equal the program bails out. So, we have one equation with one unknown which leads us to finding out the first 4 characters of the key:
(0xdf807499 - (0x1d9bdc45 - 0xad45dfe2 + 0x68656c6c - 0x41776169 + 0x69747320 + 0x64726976 - 0x6e757473 - 0x65683f21) ) & 0xdfffffff = 0x4e334431 = '1D3N' if the number is stored in little endian byte order (which it is since the Brulez processor is little endian.)
The next checks and conditions that the key must satisfy are a bit more challenging, but following a similar procedure to the one I presented above I can find some equations (in the equations that follow the variable arg[] is used to represent an array of characters that contains the first argument to the program. arg[0] is the first character of the first argument to the program, arg[1] is the second character and so on):
arg[4] ^ 0x47 must be equal to 0x2 to satisfy encrypted instruction at 0xe1bb54. This is because I know that the instruction at this address must be 3 bytes long for the rest of the program to be valid (i.e. no illegal instructions, etc.) and it must be an instruction that does not modify the stack pointer or anything else, and there is no other instruction whose first byte satisfy these conditions. This condition leads to arg[4] = 0x45 = 'E'.
To satisfy the load and compare (ldc) instruction inside the subroutine, the following equation must be satisfied: arg[4] + arg[6] = 0xa8. Since I now know arg[4] I can find arg[6]: arg[6] = 0xa8 - 0x45 -> arg[6] = 0x63 = 'c'.
Now, the second byte of the instruction at line 67 must be 3, 4, or 5 so the instruction ends up being "inc r3", "dec r3", "clr r3", or "bswp r3". So, arg[5] ^ 0x42 = {3, 4, 5, 9} -> arg[5] = 3 ^ 0x42 = 'A' or arg[5] = 4 ^ 0x42 = 'F' or arg[5] = 5 ^ 0x42 = 'G' or arg[5] = 9 ^ 0x42 = 'K'.
And finally, to satisfy the condition that the instruction at 0xe1bc11 must decode to a ret instruction (since it is the last instruction in a subroutine), I need: arg[5] + arg[7] + 1 - 0x4e = 0x42 -> arg[5] + arg[7] = 0x8f -> if arg[5] = 'A' -> arg[7] = 'N', or if arg[5] = 'F' -> arg[7] = 'I', or if arg[5] = 'G' -> arg[7] = 'H', or if arg[5] = 'K' -> arg[7] = 'D'.
Putting all the characters I have found in the correct order I get that the four possible keys are:
I realize that all this sounds confusing, but it is just additions, subtractions, XORs and a few conditions that have to be satisfied. Just follow the virtual machine program and do the math and you will understand.
After my analysis is done I can have a very accurate view of how the program the program is structured:
Here are a few interesting details and comments about 0x90.exe that did not fit anywhere else:
Q: How was 0x90.exe created? Who writes code that crazy? What language was used?
A: Well, 0x90.exe was obviously created by Nico Brulez. Because of all the low level details that I saw in the program, and all the anti-reverse engineering traps that I had to evade, I believe that the program was written entirely in assembler, i.e. no compiler intervention. However, Nico must have used a tool he wrote to automate some things such as the 175 decryption blocks and the no-operation blocks that were everywhere in the program.
"Evil Has No Boundaries !": right before starting the decryption of the 175 decryption blocks, 0x90.exe initializes the area of memory that will later be used to hold the Brulez virtual machine registers with the string "Evil Has No Boundaries !". This string will not show up when the strings command is run on 0x90.exe because it is created by doing 4-byte writes to the correct memory address. I think the string is there as a testament to the difficulty of breaking this binary due to all the evil anti-reverse engineering traps present in the program ;-)
"Exploit for it doesn't matter" - if you recall this is the message that is printed out after the "Welcome" message once a user authenticates successfully. This message is confusing and I don't have a full explanation for it. One possible explanation is that 0x90.exe has a vulnerability that in theory allows for code execution. One place where this is a possibility is in the authentication code: if you follow carefully Section 2.5, "Discovering Authentication Keys", you will notice that two letters of the key are used to decrypt (via a simple XOR) two different virtual machine instructions. This means that by carefully choosing the key one could (theoretically) control execution of the program.
Why the name 0x90?: 0x90 is the opcode for the NOP instruction (no-operation) in the x86 instruction set. Other than printing one message if the user has not authenticated, or a different one if the user has authenticated, the program does nothing.
0x90.exe has been defeated. Nothing is unbreakable and anyone with enough time, patience and motivation will always be able to get in; it is only a matter of time. Things can be made complicated and highly involved so most people give up somewhere along the way (or maybe even before starting) but there will always be someone, somewhere, that will take things until their last consequences.
And to finish, one final comment: in my opinion there are two ways to break a program like 0x90.exe: a brute force approach, and the elegant approach. The brute force approach does not require coming up with valid keys to run the program - all that is necessary is to patch the program at a specific location and force it, depending on the situation, to make or not make a jump. The elegant approach consists of understanding how the keys are generated and generating your own keys.
The thing is, both approaches require a decent amount of reverse engineering because you need to decrypt the program so you can patch it (in the case of the brute force method), and for this to happen it is necessary to evade the anti-reverse engineering traps and to understand how the program is encrypted. Once the encryption has been beaten the extra step of understanding the key generation algorithm is the fun part.
This challenge has been a great educational experience. I personally had never seen the use of a virtual machine in a piece of malware. Some of the other anti-reverse engineering tricks were also new to me.
If you have followed this far I hope you have learned something.
This appendix contains a description of every instruction in the instruction set of the Brulez virtual machine. For each instruction the length in bytes is given and if any operands are encoded instructions for decoding them are provided.
0, 0 = pushi2 n. n is encoded. decode by XORing with 0x37195411 (size = 6)
+----+----+----+----+----+----+ | 0 | 0 | # | # | # | # | +----+----+----+----+----+----+
0, 1 = pushi n. n is encoded. Add 0xadd01337 to get value (size = 6)
+----+----+----+----+----+----+ | 0 | 1 | # | # | # | # | +----+----+----+----+----+----+
0, 2 = push rx. x is encoded. XOR with 0x47 to get x (size = 3)
+----+----+----+ | 0 | 2 | x | +----+----+----+
0, 3 = pop rx. x is encoded. XOR with 0x66 to get x (size = 3)
+----+----+----+ | 0 | 3 | x | +----+----+----+
0, 4 = adjsp # (size = 3)
Adds # to the stack pointer. # is encoded. XOR with 0x45 to get value.
+----+----+----+ | 0 | 4 | # | +----+----+----+
1, 3 = xor (rx), ry (size = 5)
+----+----+----+----+----+ | 1 | 3 | y | Sz | x | +----+----+----+----+----+
Sz = size: 0 byte, 1 half word, 2 word
1, 4 = addi rx, #. x is encoded. substract 3 to get x. set zero flag based on result (0 if result 0, 1 if not) (size = 7)
+----+----+----+----+----+----+----+ | 1 | 4 | x | # | # | # | # | +----+----+----+----+----+----+----+
1, 5 = subi rx, #. x is encoded. substract 2 to get x. set zero flag based on result (0 if result 0, 1 if not) (size = 7)
+----+----+----+----+----+----+----+ | 1 | 5 | x | # | # | # | # | +----+----+----+----+----+----+----+
1, 6 = andi rx, #. x is encoded. substract 5 to get x. set zero flag based on result (0 if result 0, 1 if not) (size = 7)
+----+----+----+----+----+----+----+ | 1 | 6 | x | # | # | # | # | +----+----+----+----+----+----+----+
1, 7 = ori rx, #. x is encoded. substract 4 to get x. set zero flag based on result (0 if result 0, 1 if not) (size = 7)
+----+----+----+----+----+----+----+ | 1 | 7 | x | # | # | # | # | +----+----+----+----+----+----+----+
1, 8 = xori rx, #. x is *not* encoded. set zero flag based on result (0 if result 0, 1 if not) (size = 7)
+----+----+----+----+----+----+----+ | 1 | 8 | x | # | # | # | # | +----+----+----+----+----+----+----+
1, 9 = add rx, ry. x is encoded; substract 3 to get x. y is encoded; substract 1 to get y. set zero flag based on result (0 if result 0, 1 if not) (size = 4)
+----+----+----+----+ | 1 | 9 | y | x | +----+----+----+----+
1, 10 = ldc rx, ry. Load and compare. x is encoded; substract 1 to get x. y is encoded; substract 2 to get y. Load rx with contents of ry. reset zero flag if rx is equal to ry. set zero flag otherwise (size = 4)
+----+----+----+----+ | 1 | 10 | y | x | +----+----+----+----+
2, 0 = hlt - exit Virtual Machine (size = 2)
+----+----+ | 2 | 0 | +----+----+
2, 1 = sys - do a syscall, store 32-bit result in r0. Set flag based on result (0 if result 0, 1 otherwise.) The address of the IAT entry for the system call to make is encoded. Add 0xFEA731DE to obtain real address (size = 6)
+----+----+----+----+----+----+ | 2 | 1 | # | # | # | # | +----+----+----+----+----+----+
2, 2 = ldi rx, #. # is encoded. add 0xaefded04 to decode (size = 7)
+----+----+----+----+----+----+----+ | 2 | 2 | # | # | # | # | x | +----+----+----+----+----+----+----+
2, 3 = dec rx. set flag (0 if result 0, 1 if 1) (size = 3)
+----+----+----+ | 2 | 3 | x | +----+----+----+
2, 4 = inc rx. set flag (0 if result 0, 1 if 1) (size = 3)
+----+----+----+ | 2 | 4 | x | +----+----+----+
2, 5 = clr rx. set rx to 0. sets zero flag to zero (size = 3)
+----+----+----+ | 2 | 5 | x | +----+----+----+
2, 6 = strnchr(): searches for a specific char in the string pointed by r0. if found leaves in r0 a ptr to the found char. if not found resets the zero flag. only a maximum number of characters is searched (size = 5)
2, 7 = trap. Produce a debugger trap to debug microcode (x86 assembly) (size = 2)
+----+----+ | 2 | 7 | +----+----+
2, 8 = ld rx, (ry). load rx with contents of memory address pointed at by the contents of ry (size = 4)
+----+----+----+----+ | 2 | 8 | y | x | +----+----+----+----+
2, 9 = bswap rx (size = 3)
+----+----+----+ | 2 | 9 | x | +----+----+----+
(buggy microcode since bswap output not being written to register)
2, 10 = ldbze rx, (ry) - load byte zero extend (size = 4)
+----+----+----+----+ | 2 | 10 | y | x | +----+----+----+----+
2, 11 = ldhze rx, (ry) - load half word zero extend (size = 4)
+----+----+----+----+ | 2 | 11 | y | x | +----+----+----+----+
3, 0 = pcbe (pop, compare and branch if equal). compares the two words in the stack and branch if they are equal. the words are removed from the stack. destination address is encoded. substract 0x31337 to get real address (size = 6)
4, 0 = jmp to encoded dest. Destination is decoded by adding 0xdeadead (size = 6)
+----+----+----+----+----+----+ | 4 | 0 | # | # | # | # | +----+----+----+----+----+----+
4, 1 = jnz to encoded dest. Destination is decoded by adding 0xe1ba3e (size = 6)
+----+----+----+----+----+----+ | 4 | 0 | # | # | # | # | +----+----+----+----+----+----+
4, 2 = jz to encoded dest. Destination is decoded by adding 0xe1ba41 (size = 6)
+----+----+----+----+----+----+ | 4 | 0 | # | # | # | # | +----+----+----+----+----+----+
5, 0 = call addr (size = 6)
addr = D << 24 + C << 16 + B <<8 + A
5, 1 = ret (size = 2)
+----+----+ | 5 | 1 | +----+----+
The following files where generated during this Scan of the Month:
hide.idc: IDA IDC program to hide sections of code in a program. The addresses of the sections to hide are taken from an input file. Hiding sections of a program that only contain no-operation garbage makes the program a lot easier to follow and analyze.
xor.idc: IDA IDC program to XOR a section of a program with a byte specified by the user. I used this to decrypt from within IDA the two sections of the program that get decrypted by the Brulez virtual machine. One section was decrypted by XORing with 0x53 and the other one by XORing with 0x43. See Section 2.2.5, "Heavy Use of Encryption" for details.
0x90-n2.idb: IDA Pro database that I used until the end when reverse engineering 0x90.exe.
decrypt-0x90.c: C program used to automatically decrypt the two chains that contain a combined total of 175 decryption blocks, patch the program so these chains are not decrypted, and neutralize all the exception handlers wrecking havoc when the program is run under a debugger.
XML sources for this document: this HTML document was generated using DocBook XML. This directory contains all the files used in the generation of this document.
Performance monitoring, a x86 assembly language gem from the the Assembly Gems page.
A Crash Course on the Depths of Win32 Structured Exception Handling: excellent Microsoft Systems Journal article by Matt Pietrek.
An In-Depth Look into the Win32 Portable Executable File Format : another Microsoft Systems Journal article by Matt Pietrek.
The submission was prepared using DocBook XML, and then converted to HTML using Tim Waugh's xmlto XML converter. Editing was done on a Linux desktop using GNU Emacs and the PSGML major mode.
All the anti-reverse engineering work was done on a Linux desktop using a Linux native version of the IDA disassembler. Machine virtualization on the same desktop was used to run the program in a debugger.
Very special thanks to ...
Nick DeBaggis for his insightful comments and suggestions while I was working on this. A couple of findings presented in this document were pointed out by him (sorry for not being more specific dude!)
The fine folks at DataRescue for creating and maintaining IDA Pro, and specially for producing a native Linux version.
Nico Brulez, architect of the Brulez Virtual Machine and of this challenge, for designing such a great educational experience and for providing some fine hours of entertainment.
As always, the Honeynet Project for coming up with these nice and entertaining challenges.

subset: commoncrawl


text:
|National Cooperative Development Corporation
Home | Activities | Functions | Statistical Figures | Board | Regional Directorates | Contact |
Genesis of NCDC
The Govt. of India constituted an all India Rural Credit Survey Committee under the aegis of Reserve Bank of India. This committee submitted its report in 1954, designed and laid the foundation of farmers cooperative for mordernising agriculture and fostereing rural economic activities for the benefit of rural community. The committee recommended that while the RBI - now the National Bank for Agirculture and Rural Development (NABARD) should take upon itself the task of promoting and financing of rural credit cooperatives, the Government of India should set up a statutory Corporation for spearheading the development of other rural ecnomic activities in the cooperative sector. It was with this background that the National Cooperative Development Warehousing Board was set up in 1956. In 1963 the warehousing activity was separated and NCDC was Created.
NCDC was established in March 1963, under an Act of Parliament as a succsessor organisation to the National Cooperative Development and warehousing Board set up in 1956, in pursuance of the recommendation of the All India Rural Credit Survay Committee(1954) under the aegis of Reserve Bank of India.
Other Institutions


text:
Discover a selection of top forums epicshire circle on the internet. Come to share your passion on forums epicshire circle and meet other fans of epicshire circle. Then, why don't you create your own forum of epicshire circle ?
The Ebon Circle is a Feral Heart based Roleplay and Social Group about the Kreptis species
ebon, #circle, feral, heart, based, roleplay, social, group, about, kreptis, species
Free forum : A circle of practitioners together exploring, testing, and reporting results of the highest teachings and most advanced practices of the evolving Buddhadharma
innermost, courtyard, #circle, practitioners, exploring, testing, reporting, highest, teachings, advanced, practices, evolving, buddhadharma
Radically soft queer feminist circle reading group
This is the description
test, #circle, description
Merry Meet, Sacred Circle Coven (SCC) was created so that like minded individuals could come together to discuss and learn about all forms of the path.
sacred, #circle, coven, merry, meet, (scc), created, that, like, minded, individuals, could, come, together, discuss, learn, about, forms, path
The Sabbat have overrun Dallas for too long. The inner circle has chosen you to take backt he city. After you have fought for your right to survive, how will you continue to grow the city?
delirium, vampire, masquerade, larp, sabbat, have, overrun, dallas, long, inner, #circle, chosen, take, backt, city, after, fought, your, right, survive, will, continue, grow
The purpose of this forum is to create an open source community that is focused on fabricating the best headphones for as little money as possible using free time.
crop, #circle, audio, purpose, open, source, community, focused, fabricating, headphones, money, using
A circle of those who are bound by fate.
Ark Survival Tribe Dark Circle information HUD
dresden files game set in indianapolis 2017. focusing on a balance struggle between traditional magic, strange outsider magic, and an unknown force. post Changes.
case, #circle, city, dresden, files, game, indianapolis, 2017, focusing, balance, struggle, traditional, magic, strange, outsider, unkn
Free forum : An inclusive environment for black women to congregate and discuss that which pertains to them spiritually, holistically, and emotionally on a natural level.
path, goddess, holistic, african, black, woman, women, congregate, discuss, pertains, spiritually, holistically, emotionally, natural, queen, sisterhood, afua, sacred, womb, #circle, healer, witch, bruja, orisha, santeria
Satoshi Talk Forum
The Ninth Circle
free, forum, clan, tdsx, star, citizen, organization, pirate, orgs, ninth, #circle, guild
Free forum : This is a crossover RP of Teen Wolf, The Secret Circle, The Vampire Diairies, and True Blood!
free, forum, rule, night, true, blood, teen, wolf, vampire, diaries, crossover, secret, #circle, diairies, blood!
A private virtual writing circle.
N. C. 's 1/4 Mile Oval Dirt Bullring
Club Chairmans Circle Club Lifestyles Holiday Vacation in Puerto Plata forum
chairmans, #circle, club, lifestyles, holiday, vacation, puerto, plata
Free forum : outcasts of the Gaiaonline metal forum who have formed an alliance to create a safe and productive place to discuss and discover acts from every spectrum of extreme music.
free, black, #circle, gaia, outcasts, gaiaonline, metal, have, formed, alliance, create, safe, productive, place, discuss, discover, acts, from
The Healing Circle is a support and community group for shamanic practitioners to ask questions, share experiences, and generally work together.
healing, #circle, support, community, group, shamanic, practitioners, questions, share, experiences, generally, work, together
Free forum : Many rpgs grown from a close circle of friends.
Free forum : Not an official Crimson Circle forum. This forum is Inspired by Shaumbra for the folks who are part of the family known as Shaumbra.
PromotionCircle, is a online advertising community where the limits and possibilities are endless, advertise what you want and discuss several topics. http: //thepromotioncircle. forumotion. com Removed on: 08/04/2016
advertising, promotion, services, free, forum, website, submission, traffic, exchange, marketing, search, engine, yahoo, google, bing, submit, your, site, advertisement
A realistic WolfQuest role-play pack centered on modeling successful coexistence between wolves and humans.
#circle, ranch, pack, realistic, wolfquest, role-play, centered, modeling, successful, coexistence, wolves, humans


text:
Kathleen Thomas, MSW
Licensed Clinical Social Worker
4559 Old William Penn Hwy., Murrysville, Pennsylvania 15668
Working with families, as all of the members are in constant flux, is a complex challenge, but can be a rewarding and learning experience for all. Having a therapist to help sort out agendas and brainstorm new approaches to manage the family system can be educational and rewarding. Being able to have new roles in a family system can change self esteem and self confidence.
Summit Psychological Services, Ph. D
1350 Old Freeport Road, Suite 1A, Pittsburgh, Pennsylvania 15238
Family Therapy provides family members, whether its two members or the entire family, the opportunity to voice their feelings, emotions and concerns. The participants may feel more comfortable sharing their concerns in an atmosphere that is open with a nonjudgmental professional overseeing the discussions. Based on your family's current circumstances, a unique treatment plan will be created to fit your families specific needs. Commonly used therapies include the following: Structural Family Therapy (SFT) Solution-Focused Brief Therapy Bowen Family Therapy family therapy focuses on treatment of the family system not the symptomatic family member or problem.


text:
A study in Arabia on food hygiene, good manners and better health
Washing all fresh produce including carrots, lettuce, tomato, cucumber helps stave off E-coli and so does 'good manners'.
Germs thrive all around us "even on us" and how we minimise their attack is dependent on how we take care of ourselves and our surroundings, especially those involved with food. The recent E. coli scare in Europe has yet again reminded us how important personal hygiene, and thoroughly cleaning everything we consume is, as the source of the sickness is still uncertain and new strains are being discovered every other day.
Dettol's Habit (Hygiene: Attitudes, Behaviour, Insight and Traits) study, conducted in various countries including the UAE and Saudi Arabia, found that people who have good hygiene habits (such as effective hand washing and household cleaning) and good manners (such as covering your mouth when sneezing or coughing) are almost two and a half times more likely to have good health and be less prone to infection.
Responsible living
"Previous studies have shown that intensive hygiene education plus the regular use of disinfectants (soap, surface cleaner, and skin disinfectant) can significantly reduce the risk of illness among children," says Tariq Madani, professor of medicine and infectious diseases, faculty of medicine, King Abdulaziz University, Jeddah.
He was in Dubai recently for a seminar organised by the Hygiene Council.
"These new findings from the Habit further emphasise how improved hygiene behaviour can effectively stop the spread of germs. Practising good hygiene is not just the concern of women, more conscientious people or those who live in a dirty environment; it is everyone's responsibility and is vital in breaking the chain of infection" he adds.
How then can we create a cleaner home environment?
"Regular disinfection of frequently touched surfaces, particularly kitchen surfaces and taps, is essential. Many disinfectants are available for household disinfection. However, it is better to use the well-known brands. Bleach is acceptable but it has to be diluted at least ten times with water before using it to disinfect surfaces. The bleach solution needs to sit on the surface to be sanitised for about ten minutes to be effective," Madani says. He also said disposable cleaning implements are better. "The use of disposable mops and scrubs is indeed preferred over reusable ones, particularly when used to clean or disinfect kitchen surfaces where food is handled or served. If reusable mops and scrubs are used they have to be frequently washed and disinfected."
After minimising germs from the surfaces, how can we reduce, if not eliminate, contamination from food?
"Washing fruits and vegetables is important whenever you cook. You have to check the quality and segregate the good items and dispose the bad ones," says Sous Chef Black of Radisson Blu Dubai Media City.
Sanitising solutions
"While washing fruit or vegetables, never wash and sanitise different types of fruit or vegetables together. It always should be one type at a time. First, wash them, removing all visible dirt and check for worms or other pests, then wash properly. Second, transfer the washed fruit or vegetables in another bowl or sink with water using sanitising solution. Make sure that it is completely immersed in the solution and let stand for five minutes. Fill another bowl or sink with water. Ensure it is clean for final rinse. Immerse and rinse the produce properly. Let it stand for at least five minutes in a strainer to drain the excess water."
Speaking of sanitising solutions, are they really effective or just marketing gimmicks?
"The off-the-shelf washes/tablets may rid fresh produce of most bacteria, but water works just as well. Water can remove 98 per cent of bacteria when it's used to rinse and soak produce. Rinse under running water. For extra protection, adding one part vinegar or lemon juice to three parts water helps, but you don't need to use any soap, detergents or special cleaners. Rinse food, even if you are going to peel it. Use a scrub brush to remove additional dirt and bacteria. Dry produce with a clean cloth or paper towel to wipe off more bacteria," Madani says.
Nils Al Accad, CEO, Organic Foods & Café, feels "they are effective for cleaning bacteria, on the surface but they do not remove pesticides that have soaked into the plant or fertiliser that is drawn up through the roots", which may have been the case in the E.coli scare. So is it safer to buy organic food only?
"No. Let's wait to get the full facts," Al Accad says. "Did you know there is E. coli on a lot of food we eat? It is just in small doses and not a dangerous strain. The key issue is, you have to see if the recent incident is linked to organic farming practices or not. The fact is, this could have happened in conventional farming in the same way. The latest information I have says this was not from cow manure and maybe from water and in this case the issue is that it is a new strain of E. coli that probably mutated."
Professor Tariq Madani's kitchen hygiene tips are as follows:
- Wash hands frequently with disinfecting soap before preparing food, particularly when you intend to handle food items that are served uncooked such as salad and fruits. Hands should also be washed after touching raw food, especially meat, and after going to the toilet.
- Never use the same chopping board or utensils for raw meat and ready-to-eat food without washing the board and knife thoroughly in between.
- It is especially important to make sure poultry, burgers and sausages are cooked all the way through.
- Make sure you keep your fridge temperature at less than 5°C and your freezer at less than -18°C.
- Store fresh and frozen food in the fridge or freezer as soon as possible after you have bought it. This is especially important when the weather is hot.
- Keep raw meat and seafood separate from other foods. Store raw meat in an airtight container at the bottom of the fridge to prevent juices or blood dripping on to other food.
- If you're keeping cooked leftovers, allow them to cool to room temperature before you store them in the fridge. Make sure you use up any leftovers within two days.
- Throw away food that has passed its use-by date.
By Manjari Saxena


text:
Policy # TBD
Title: Tuition Payment for Students Exceeding 165 Degree Credits
Current Version Approved: TBD
Primary Responsible Office: Office of the Provost
Secondary Responsible Office: Office of the Registrar
This policy describes procedures for determining tuition payments for students who exceed 165 earned degree credits and are seeking a baccalaureate degree from UW-Green Bay.
UW System policy has directed each institution to:
This policy covers all resident undergraduate students pursuing their first baccalaureate degree, including students simultaneously pursuing a double degree or double major.
This policy applies to all UW System earned credits and WTCS transfer credits accepted toward a degree. Credits transferred from other institutions, as well as other types of credit or coursework for which credit may be awarded (such as advanced placement, retroactive credits, credits by examination, remedial credits, etc.) are not included in the credit limit.
Starting in the fall of 2004, all resident undergraduate students who have accumulated 165 credits (or 30 credits more than required by their degree programs, whichever is greater) will be charged a surcharge, equal to 100 percent of the regular resident tuition, on credits beyond that level.
Prior to each semester's priority registration period, the Registrar's office will identify students who will have more than 145 credits but less than the 165 credit limit prior to their next enrollment and who are not scheduled to graduate. Totals will be based on the criteria in the "Applicability" and "Exclusions" sections of this document. These students will be sent a 'Warning of surcharge' letter referring them to their adviser. The letter will include policy information as well as appeal/waiver information. A copy will also be sent to the adviser.
Prior to each semester's priority registration period, and using the criteria listed in this document, the Registrar's office will identify students who will exceed the 165-credit limit prior to their next enrollment and who are not scheduled to graduate. These students will be sent a 'Notification of surcharge' letter. The letter will include policy information as well as appeal/waiver information. A copy of the letter will also be sent to their adviser as well as to the Bursar.
Surcharges will be assessed as needed by the Bursar based on the notification letters and any subsequent waivers.
The Registrar's office will include and maintain policy information, including guidelines and procedures on their WEB-site. Initial notification of students would begin in October 2003.
The Provost's office will be responsible for the review of programs with credit requirements in excess of 130 credits.
Appeals/Waivers of the surcharge will be submitted and approved thru the Academic Affairs organizational structure. Adviser, unit chair and academic dean's approval is required for a surcharge waiver. If approved, the waiver should be forwarded to both the Registrar and Bursar.
Undergraduate special students are not subject to the credit limit.
Students pursuing post baccalaureate certification or licensure are not subject to the credit limit.
Minnesota reciprocity students are not covered by the policy under the existing compact and will not be subject to the surcharge until such time that Minnesota adopts a similar surcharge.
Questions regarding the implementation and interpretation of this policy should be directed to the Provost and Vice Chancellor for Academic Affairs.
APPROVED: __________[Signature on File]___________ DATE: October 21, 2003
Bruce Shepard, Chancellor


text:
It was sudden and effective, sort of like a heavyweight who lands a big punch early.
Only this time, it was East tailback Ula Tulutau supplying the blow. On the third play of Friday's 4A Region 6 tussle at Highland, Tulutau burst through a gaping hole between the tackles and rumbled 53 yards untouched for a touchdown.
The blow staggered the Rams for what looked like the entire first half as the undefeated Leopards raced out to a big lead and an eventual 34-13 victory.
East High was also playing for its head coach Brandon Matich, suspended a game for using an ineligible player earlier this season.
"We were very sad we lost the big guy," East quarterback Issac Valles. "It also pumped us up, and we were ready to play."
That was obvious, as the Leopards (8-0, 5-0) gained more than 200 yards of offense in the first half and more than 350 for the game behind their hulking line.
Tulutau rushed for 113 yards, but Valles ran for 139 yards, often tacking on more yardage after the initial hit.
"It was a huge game-changer," said Valles of Tulutau's burst for 6 yards. "Oh my gosh, we have the best line in the state, no doubt. Wherever they go, we go."
East was also a bit lucky, taking a 14-0 lead on a heave of a pass from 36 yards out that was batted around by a couple of players on both teams before Preston Curtis plucked it out of the air to give the Leopards a 14-0 advantage in the first quarter.
"It kind of stunned us," Highland coach Brody Benson said of Tulutau's opening score. "We kind of pushed the panic button. In the second half, we were settled down and executing. At least we settled ourselves down."
The second half was a much different story for Highland (5-4, 3-2). But miscommunication between Ram quarterback Austin Peterson and his receivers was never really solved.
Peterson, the engine behind Highland's offense, finished the night completing just 3-of-12 passes with two interceptions.
"We just weren't dialed in," Peterson said. "We had a great week of practice. I don't understand why we weren't dialed in."
Highland managed only 91 rushing yards in the first half, 75 of those coming on Adam Webber's 75-yard touchdown sprint around the right end.


text:
Kaitlin Zablotsky has received an appointment to the Fulbright Summer Institute to study at Durham University in the United Kingdom in one of the most prestigious and selective summer scholarship programs operating world-wide.
Kaitlin, a sophomore at Santa Clara University and a graduate of St. Francis High School in Sacramento, was selected from a strong applicant pool to study in the U.K. on a four-week summer program where she will participate in a major archaeological project. Kaitlin will play an active part in the excavation of one of the richest archaeological landscapes in the world, the Roman Empire in Britain at Binchester, and gain first hand knowledge of U.K. archaeological professional practice. In addition to field work, Fulbright participants will engage in a rigorous academic program as well as experience the rich culture of the U.K.
Upon receiving the appointment, Kaitlin said, "Studying in the United Kingdom is a dream come true for me. I've always loved British culture and history and can't wait to experience it firsthand."
Each year, the commission supports around 50 U.K. and U.S. undergraduate students to undertake a demanding academic and cultural summer program at leading institutions. The commission selects participants through a rigorous application and interview process. In making these awards the commission looks not only for academic excellence but a focused application, a range of extracurricular and community activities, demonstrated ambassadorial skills, a desire to further the Fulbright Program and a plan to give back to the recipient's home country upon returning.
Created by treaty in 1948, the U.S.-U.K. Fulbright Commission is the only bi-lateral, transatlantic scholarship program offering awards and summer programs for study or research in any field, at any accredited U.S. or U.K. university. The commission is part of the Fulbright program conceived by Senator J. William Fulbright in the aftermath of World War II to promote leadership, learning and empathy between nations through educational exchange. Award recipients and summer program participants will be the future leaders of tomorrow and support the special relationship between the U.S. and U.K.
Notable alumni of the US-UK Commission include: Malcolm Bradbury, novelist; Liam Byrne, politician; Milton Friedman, economist and Nobel Prize winner 1976; Charles Kennedy, politician; John Lithgow, actor; Tarik O'Regan, composer; Sylvia Plath, poet; Lord William Wallace, politician; Ian Rankin, novelist; Sir Christopher Rose QC, judge; Baroness (Shirley) Williams, politician; Vanessa Heaney, journalist BBC World Service; and Toby Young, journalist and playwright.
The commission is funded partially by the Department of Business, Innovation and Skills in the U.K. and the U.S. Department of State, with additional support coming from a variety of individual and institutional partners.


text:
APG-L ArchivesArchiver > APG > 2008-08 > 1219686830
From: Anne Roach <>
Subject: [APG] ?Fundamental Genealogical Principles?
Date: Mon, 25 Aug 2008 11:53:50 -0600
References: <001901c906d1$3d322dc0$0401a8c0@bearlet>
In-Reply-To: <001901c906d1$3d322dc0$0401a8c0@bearlet>
Hello fellow professionals,
I have two questions for you. I was recently asked what the most fundamental principles that identify sound genealogical research. Since many minds are better than one, and rather than limit myself to my own perspective, I request from you, my peers, your perspective on this question. What are the key principles that identify sound genealogical research?
The second question is a bit difficult to answer, because when we think of genealogy software, we think of what it will DO, not how it is built. I am not asking about what a piece of software should DO. So applying the concept of sound genealogy research principles to software, what do you feel should be the primary considerations for preparing the foundations of genealogical (pedigree display) software? In other words, what is the framework on which someone should build a tool in which to store genealogical data?
I look forward to your responses!
Anne Roach
NOTICE: This email message is for the sole use of the intended recipient(s) and may contain confidential and privileged information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message.
This thread:
|[APG] ?Fundamental Genealogical Principles? by Anne Roach <>


text:
I would take your advice one step further and be sure that you have hidden your address in the Places for Business Dashboard if either you do not accept clients at your address or if you are located in a residential area
An Important Update to Google+ Local for Home Performance Businesses.
Okay, folks. We're fully aware that we've been inundating you with updates to Google's local business guidelines lately; but the fact of the matter is that they're extremely important for small businesses in our space. Getting it right can drive a lot of business to your company, and getting it wrong presents a pretty big risk of getting stuck at the bottom of the Google well.
Mike Blumenthal, one of the leading experts on local search, wrote a post declaring categorically that service area businesses (SABs) that have merged their Places pages with their Google+ pages should DELETE those pages, and stick to the Places dashboard for now.
Virtually every business in our industry is a service area business rather than a storefront, so this applies to us all.
From the rollout of the G+ Local Social merge and bugs showing up when service area businesses attempted to hide their address, Google has said that service area businesses (SABs) should NOT merge their Places listing with their G+ social page. Well, some SABs did not get the message (big surprise eh?) and the question is what should they do now. The answer: Delete the Merged page and rely solely on the dashboard to manage the listing.
Peter (our CEO) chimed in with a comment asking for clarification:
Mike–I'm trying to understand the potential harm here. Assuming that a service business isn't afraid of listing their physical office address, even if not serving customers there, where is the downside? At the moment, we're not seeing that anything sticks on G+ Local pages–no photos, no videos, no reviews, no updates, no verification calls or postcards. But on merged pages, we're at least able to get photos and videos to take. Posts at least allow for some content and engagement. And I've been unable to detect any harm to local rankings. (Although in checking just now for "energy audit los angeles" I notice that Building Doctors now displays two separate Google+ page links, one to Posts and one to About.)
Here's Building Docs merged page:https://plus.google.com/u/0/101441141718220114156/posts
Blumenthal promptly responded:
Google REQUIRES that a business that does not serve customers at their location to HIDE their address. Failure to do so will result in a take down and the dreaded purge to the freezing cold "we currently do not support" siberia.
Photos will take from the dashboard but they take 4-5 weeks. Videos will not. But so few people actually make it to the Local+ page it is not that important if a photo is missing.
Linda Buquet, another local search expert, then chimed in:
Peter THOUSANDS (I believe hundreds of thousands) were delete due to not hiding address. Many were down for months, so it's nothing to mess around with.
The double G+ links you are seeing in the SERPs is a new display issue that just started being reported. I did some investigating and think I figured out what's up. I attempt to explain it here and show screen shots, so look and see if this is the same issue. Seeing Double? 2 G+ Local Links in SERPs? Here's Why?
So, if you've merged, we HIGHLY recommend deleting that page for now. We understand that this is pretty frustrating; rest assured a lot of other small business owners and marketers across the country are feeling your pain.
Keep you posted with any updates.
@Mike: thanks very much for chiming in here. For everyone: as we said above, Mike Blumenthal is probably the leading authority on Local Search so heeding his advice is the smart thing to do.
His blog about Local is excellent: http://blumenthals.com/blog/


text:
It appears you have not yet Signed Up with our community. To Sign Up for free, please click here....
Cancer: Thyroid Message Board
sory for all the posts I am just freaking out
All times are GMT -7. The time now is 08:10 PM.
Site owned and operated by HealthBoards.com


text:
You, too, can make a Mexican Red Knee Tarantula for your 2nd grader, the night before it's due. All you need is a text from your friend at around 7pm, casually mentioning the spider project due in the morning that you know nothing about, some pipe cleaners, and a small stuffed monkey.
My kids. They are in full form this year. It's impressive, the number of projects and reports and time-consuming assignments they save for the wee hours of the night before it's due. My favorites have been: reading an entire Shakespearian play and writing a 6 page report on it, and starting to memorize the Gettysburg Address, 30 mins before bed. (HIM: "Four score and seven years ago..." ME: "Can't you work on that later, it's bed time, you gotta get up at 4:45am." HIM: "Can't. It's due tomorrow. Gotta know it all by memory. Four score and seven years ago..." ME: "AND YOU'RE JUST NOW STARTING IT!!!" HIM: "Yes. Four score and seven years ago...")


text:
On June 2 2014 my wife and I decided to head to the Hard Rock Cafe to have some lunch. Our original plan was to eat at a mall in the area, but the only thing they had was a food court and that just wasn't what we wanted. We are both on a diet plan and food court food just isn't what we wanted to do. So we figured why not the Hard Rock Cafe. They should have some pretty health options and it is close to where we were. Off we go to the Cafe!
Very nice place! Cafe is clean and neat and the service was pretty damn good. WE love the gift shop. We bought a few things for our selves and family members back home. Lets get into why you are reading this. You want to know how the food was! We didn't get many items, but here is what we did get.
These were really tasty and really hot! Which I loved! By the time I ate all 10 of them my lips were on fire. They had even turned red and gotten a little swollen. No breading was nice and the skin was crispy. There was a lot of sauce on them. The cost for them was 6,097.56 colones and that is about $11.00 so that is about $1.10 a wing. A bit pricey. We used to sell wings in my pizza shop for .75 per wing regular price and would put them on special for .50 and even sometimes .25. They were very good. These were the Heavy Metal sauce just FYI.
OK, my wife and I got two of these. It was a pretty good salad. Taste was spot on and they both looked the same so the consistency was there. Very little dressing on it, but you knew it was there. The two salads cost us 13821.14 colones so that is about $24.93 again a bit pricey, but it was a good salad.
We ended our meal with 2 coffee's. Got the Americano black of course. Said this was Costa Rican coffee that they used, but I have my doubts. Didn't like it much. I had to put 3 sweeteners in it to make it drinkable. Now if you like a strong bitter coffee this is the coffee for you no doubt. We paid 2113.82 colones which is about $3.81 so not bad for two cups of coffee. You will pay way more in a starbucks! So really the only reasonable price was the coffee and only if you like this kind of coffee. We also had 1 Pepsi light at 1544.72 colones and an unsweetened ice tea for 1544.72 colones. Their individual prices is about $2.79 and that is expensive. Not as expensive as Te Con Te the other day, but up there. Most times the drinks like this cost about 1000 colones, maybe 1200. Our total bill with tax and tip came to 30,900.00 colones or $55.74. That really is a big pricey for 2 salads, 10 wings, 2 drinks and 2 coffees. Hey Its a chain so you expect to pay more.
All that sound wonderful doesn't it! Well with the exception of the price. I though so as well. I thought, OK the wings were a stretch on the healthy eating side, but how bad could they be? They were not breaded! Got the salad and it have very little dressing on it so thought we were doing pretty good. WRONG!!!!!! This meal was almost 3K calories. I went home and looked up the items so I could put them in my fitbit log and have an idea of how many calories I had eaten today. I was shocked and almost fell on the floor when I saw it. When it comes to healthy food this place is not the place for you! It is horrible!!!!! So if you are tying to eat healthy avoid this place like the plague!!!!!!!! Do not and I reapeat do not go here. The following is a food chart from their own website. They only give the calories and sodium. I have looked and looked on the internet to find more information and I can't. Very strange if you ask me.
Hard Rock Cafe – Print Menu If I would have known I would have picked a salad with less calories and I would have never gotten the wings.
So here are some random photo's I took just to try and forget what we just experienced. Read over the menu, you will be shocked!
So, lets get to the final on this one. The food was good as far as taste goes, the service was excellent, the place was clean (it is brand new so it should be), the bathrooms were nice and clean. The price is a bit high. I should be able to give them 3 out of 5, but I just can't. I have to give them 2. I have to take off for the price to value and the very, very, very bad nutrition of the food. I just can't bring myself to give them more. I tried to calculate how they could come up with those number on the calories. I just couldn't do it. I have no clue what they put in there to do that, but it is insane! Well another one down the drain. Lesson here is don't go to Chain restaurants in Costa Rica! Stick with the local places. You will get a good meal for a fair price.
Pura Vida!


text:
A Tacky/Impersonal/Genius Way To Deal With Office Birthdays
God, not another one, you think, about the endless cycle of office birthday parties. The infinite number of birthday cards being passed around for Doug in accounting or Jenny in receiving––people you've barely nodded your head toward in the hallway. "Do I have to say something nice about people I barely know again," you think. Well, the lazy bastards at one Redditor's office seem to have found a supremely lazy solution–A multiple choice check box all-purpose birthday card. Here, Joe is congratulated by most of his colleagues for getting another year old. Most of his colleagues, that is, except for Peter and Steve F., who are possibly throwing shade Joe's way. Happy birthday Joe, from … all of us. [Digital Spy]


text:
Branded Executive Resume Writer
6 Ways to Stand out in a Tough Job Market – U.S.News & World Report Interview
Read this U.S. News & World Report article where I am interviewed by Careers Expert Miriam Salpeter in her On Careers Column on 10/23/2011.
When you're looking for a job, it's easy to fall into the trap of applying and waiting to hear from an employer to see if you won a chance to interview. What's the problem with this "apply only" strategy (also known as "spray and pray")? It puts too much power into other people's hands. Job seekers who seize control of their searches have a much better chance of landing opportunities than those who spend all of their time looking for open opportunities and applying. Lisa Rangel is managing director of Chameleon Resumes, contributor to Michelle A. Riklan and David Riklan's, 101 Great Ways to Enhance Your Career, and author of the ebook, The Do-It-Yourself Branded Resume Kit.
As a search firm recruitment leader for over 13 years who partnered with Fortune 500 and boutique firms to source top talent, she sat on the proverbial "other side of the desk," hiring people to fill clients' positions. She advises job seekers to take steps to ensure it's easy to find them for the jobs they want. "Posting an ad to recruit for an open position is one of the last tactics a recruiter wants to use," Rangel says. Once a position is available online, many recruiters receive a plethora of ill-qualified applicants. [See The 50 Best Careers for 2011.]
Rangel advises candidates to distinguish themselves from the rest of the applicant pool using these techniques:… Continue Reading…