January 2009 - Posts

PS Batch... Command: It's Like Watching a Movie
01-08-2009 2:35 PM

Do you have a digital camera? Do you need to resize a thousand photos?

Yes, I know, there are free batch resizers available online, and even you guys can code one if you felt like it. So for those who do not know how to make one, or is too lazy to get one, but luckily has a copy of photoshop, here's something for you. There's a command in the File menu that often gets ignored (at least by the people I know) -- it's the batch command. Ignored simply because they think that it's a hassle to set up. It's actually so easy, c'mon!

Before you can use this command, you should have an Action. Actions are like "macros" - you can record anything you do in PS and recreate it with a single click. Pretty neat huh! We'll make a simple batch resizer. Let's start!

  • Open up an image.
  • Open the Actions panel.
  • Click the "New set" icon (Looks like a folder) and name it.
  • Click the "New action" icon (Looks like a folded paper) and name it.
  • Click the "Record" icon (Errr... looks like a record button). LOL.
  • After step 4, you can actually do whatever you like, but for the examples sake, Image > Image Size... let's just try to set it to 640 x 480. Click ok.
  • Press the "Stop" icon in the Actions panel (The square one..)

Now let's use that create action in the Batch command. Here goes.

  • Click File > Automate > Batch...
  • (From hereon, see screenshot below for reference) Choose the set we created.
  • Choose the action we created. (Since isa lang naman yung action sa set natin, it will be the initial pick.)
  • Source - choose what's appropriate. Usually it would be "Folder".
  • (Assuming Folder) Click Choose... button, then point to directory containing pictures/images to be resized.
  • Destination - I usually choose "Folder" here as to preserve the original source. But if you don't need the originals, choose "Save and Close".
  • (Assuming Folder) Click Choose... button, then point to directory where you want the resized images to be dumped to.
  • (Assuming Folder) You can assign the new resized files a new name here. There are a lot of choices in each dropdown box. You can also explicitly type it out. Just remember to at least concat an incrementing value to avoid overwriting stuff.
  • Click OK!

NOTE: You can use Batch... for anything! I only used resizing as an example. If the Actions can record it, you can Batch it.

See, was that too hard? Now you can sit back and watch PS do the work for you. As the title goes, "It's like watching a movie." Hehehe.

by modchip | with no comments
Filed under:
cvega's Kill the Nag: An In-depth Dissection
01-08-2009 1:11 PM

Ok, here we go again! This is my solution for cvega's Kill the Nag challenge. Let's review the conditions.

Method: Patch
Difficulty: Easy
Restriction: Help->About action should remain function, killing the dialog from resource is prohibited.

You can see from the nag-screen from the screenshot, it says that the program expired from trial and it annoy you every 15 seconds by showing you the reminder nag-screen (hint!).

See the attached program, and take your time it's not easy.

We have a couple of things we can use here.

  • Killing the dialog using a resource editor is prohibited. Check!
  • He said dialog, so chances are, the DialogBoxParam will be called somewhere at startup. Check!
  • There is a timer, probably set by a SetTimer. Check!

Let's check out the target in its "untouched" form.

Very simple. We can do 2 approaches here. 1, destroy the dialog by skipping any DialogParam calls; 2, Destroy the timer (I mean, don't let it start).

APPROACH 1: Skip the DialogBoxParam call.

I'm assuming you already have OllyDbg. If you don't, please fetch it @ http://www.ollydbg.de, it's free.

Fire up Olly, load our target (manage.exe). let's search for a Dialog call. Look just a few lines after the line in which we landed, do you see the call. It might or might not be the call we want, but since we're already there, let's try it out.

There's a conditional instruction before the call, I don't know what it is (possibly the countdown? A little help here chris), so let's try our luck here. What we can do is instead of a conditional jump, will change it to a forced jump (JMP) to the RET instruction - fully avoiding the DialogBoxParam call. So, highlight the JNZ short line, then press the SpaceBar. Change it as I've changed it in the screenshot. What it does is what I just explained. LOL.

Run the program in the debugger. Did it work?!? It did for me! Solved!

But remember, any changes that you made are temporary. If you want it permanently changed, you must - right click on the CPU window, highlight "Copy to executable" then click "All modifications".

Then click "Copy all"...

A new window will pop, right click on it, click "Save file". Choose a new filename and your changes are permanent now.

Congratulations, you've just solved cvega's challenge!

APPROACH 2: Prevent the timer from starting.

Almost the same as approach 1, but this time, we will skip a call to the SetTimer. All you have to do is to find that call, a few page downs from the start of the code will lead you there, then just change the 1st push to a jmp to the line after the SetTimer call. I guess I don't have to fully illustrate each step here since as I've said, it is very similar to the first approach. So maybe I'll just drop a few screenies.


So there you have it, 2 approches for one problem. By the way, here's my fixed manage.exe. I know there are other ways to solve this, but you have to find those yourself! Until the next challenge! Bye!

cvega's Save The Devil: A Walkthrough
01-08-2009 11:22 AM

Since the "Save the Devil" challenge from cvega seems inactive for sometime now, I decided to write my complete solution for it, in case anyone is wondering how I got the correct numbers, and eventually "saved" the devil. So here goes.

There are a couple of things that you need in order to follow me with this guide. You need OllyDbg (A free debugger @ http://www.ollydbg.de/) and a Hex2Char Converter (any would do, to make things easy).

Done getting the tools?

First thing to do is to get to know the target , which is devil.exe . Run it, and observe it. Let's see, there's a timer... there's a textbox... there's a button... So I'm guessing that we must type something on the textbox (duh!?!). Ok, let's try something before the time runs out, then press go. Hmmm.... nothing happens. let's see what happens if the timer reaches 0 - "The Devil is DEAD!!!" (Take note of this message) - that's not what we want.

Let's check cvega 's solution conditions again.

To save the devil, you need to enter the code to unlock the devil's lifestream before you run out of time!

Hint: The code is 8 digit long composed of all numbers!

Cool! There's a hint! This hint is actually the easy way out for this challenge. If he had not mentioned that, it will be alot harder for us to solve this. Ok, back to the challenge, he said 8 digits -- so there's probably a counter set for that, usually stored in the appropriately named "Counter Register", ECX. Let's take note of that.

Here's where the real fun starts. Fire up OllyDbg, and open our target, "devil.exe". Whoa! What's all these. Behold, the disassembled code of devil.exe. Eeekkk! Anyways, remember the message that was displayed when the devil died, let's use that as a starting point. Right click on an empty space in the CPU panel, then click "Search for" then click "All referenced text strings". A new window will appear. Let's look if the message is here.

Oh goodie, there's 2, but the actual one is the one with the three "!", double click that and let's see where it takes us.

Ok, so far so good, there's the message when we fail to save the devil, and above it is the message when we actually saved the devil. So this means that the calculation for the correct number is somewhere above this code. Let's scroll up a little to find out.

Yahoo! Did you spot it? Did you remember cvega 's hints? 8 digits? There we have it!

Let's set a breakpoint to get a better view of what's going on. Hit F2 on the line with the code MOV ECX, 8. The address will have a red marker which means a breakpoint is set. Once done, run the program. (If you receive an error about something unreadable yada yda, just close the program and run again. It will fix itself after a few tries.) Enter any number on the textbox, then click go. You should break. Let's step over the code using the F8 button.

Let's study the code.

01 004012BD MOV ECX,8 ; This is the counter
02 004012C2 JMP SHORT devil.004012DA ; Jump to line 16
03 004012C4 LODS BYTE PTR DS:[ESI] ; Get a character of your input
04 004012C5 PUSH EAX ; Stored character pushed to stack
05 004012C6 MOV EAX,EDX ; Copy something to EAX, stored digit is overwritten
06 004012C8 POP EAX ; Restore top value of stack, stored digit back to EAX
07 004012C9 ADD AL,18 ; Add 18 to stored digit
08 004012CB SUB AL,0C ; Subtract 0C to stored digit
09 004012CD ADD AL,18 ; Add 18 again...
10 004012CF SUB AL,24 ; Subtract 24, duh, it's back to its original value
11 004012D1 XOR AL,4E ; THIS IS THE ONLY IMPORTANT BIT...
12 004012D3 MOV EDX,EAX ; Sigh... Looking at the algo, I think it's quite useless,
13 004012D5 SUB EDX,0E ; except for line 11, so let's carry on to the comparison
14 004012D8 STOS BYTE PTR ES:[EDI] ; section... which is Line 18.
15 004012D9 DEC ECX ; ECX -= 1
16 004012DA CMP ECX,0 ; Is the counter equal to 0?
17 004012DD JA SHORT devil.004012C4 ; If counter is > 0, got to line 3

Almost everything is junk. But line 11 does something, so let's take note of that. let's look further down to the conditional part of the code;

18 004012DF LEA EAX,DWORD PTR DS:[404175] ; Copy something to EAX as pointed by address 404175 then
19 004012E5 MOV EDX,DWORD PTR DS:[EAX] ; Copy 7A7E7F7F from EAX to EDX, whatever that is...
20 004012E7 MOV ECX,DWORD PTR DS:[EAX+4] ; Copy 76787677 to ECX...
21 004012EA LEA EAX,DWORD PTR DS:[40407D] ; Copy our string as pointed by 40407D
22 004012F0 SUB EDX,DWORD PTR DS:[EAX] ; EDX = 7A7E7F7F - our last 4 digits
23 004012F2 SUB ECX,DWORD PTR DS:[EAX+4] ; ECX = 76787677 - our 1st 4 digits
24 004012F5 ADD EDX,ECX ; Add EDX and ECX result in EDX
25 004012F7 OR EDX,EDX ; Check if EDX is equal to 0
26 004012F9 JNZ SHORT devil.0040136E ; If not zero, our number is WRONG!
; EDX will only be 0 if 7A7E7F7F 76787677 (with extra Xor'ing))
; matches our number.... hence...

So this is what's happening. Each character of the number we input is XORed with 4E, and then subtracted with the correct one. So naturally, if ours matches the one cvega coded, the result must always be zero! And since the correct one is hardcoded, we can easily extract it. The answer is right below our noses all the time! It is;

18 004012DF LEA EAX,DWORD PTR DS:[404175] ; Copy something to EAX as pointed by address 404175 then
19 004012E5 MOV EDX,DWORD PTR DS:[EAX] ; Copy 7A7E7F7F from EAX to EDX, whatever that is...




20 004012E7 MOV ECX,DWORD PTR DS:[EAX+4] ; Copy 76787677 to ECX...




See? Since it's hex, it will be in reverse. The correct (raw) string is 777678767F7F7E7A. Take out your converters and let's convert away, character by character.

Hmmmmm.. this is weird, 77 is w, 76 is v... The correct answer are digits, but were getting alpha characters... So why's that? Check line 11 of the code. Each character must be XORed by 4E! Let's try that.

77 XOR 4E = 39h
76 XOR 4E = 38h
78 XOR 4E = 36h
76 XOR 4E = 38h
7F XOR 4E = 31h
7F XOR 4E = 31h
7E XOR 4E = 30h
7A XOR 4E = 34h

Then let's convert each to a char;

39h = 9
38h = 8
36h = 6
38h = 8
31h = 1
31h = 1
30h = 0
34h = 4

Ok, we got - 98681104; It's all digits, it has 8 characters. Do you think we got it? Only one way to find out...

We did it!!! We save cvega 's devil!!! I hope you learned a lot! Until next time! Bye!

Optional: You can also try to stop the timer for additional challenge if you like. :D

PS: Keith, puwede ba ito? Hehehehe. :D