
peterthepigeon
Members-
Posts
112 -
Joined
-
Last visited
Everything posted by peterthepigeon
-
It is, but sadly I already have all that information nuclear explosion from super fast firing obelisk lags the game beyond all belief but i confess nuclear obelisk is a nice idea for a custom map perhaps....
-
-
sure why not laser only draws for structures, but it shouldn't be too hard to modify it to draw for units and infantry
-
Guess I wasn't paying attention. I already beat the game so it's no biggie. Tib Sun is next! Should've played the demo, it doesn't have garbled transmission so you know you're supposed to blow up the airstrip.
-
Working on reversing the setup routines for the core stuff, bullets.ini, etc. Should be done with this next week and have it setup on the repo for people to follow. For fun: CPU Disasm Address Hex dump Command Comments 0041D1B1 |. 8066 69 9F AND BYTE PTR DS:[ESI+69],9F CPU Disasm Address Hex dump Command Comments 0041D872 80E5 9F AND CH,9F This resets the obelisk charging animation. Change the immediate to 0xFF or whatever. Then your obelisk can super fire. PS this code only executes if the obelisk's weapon is the laser.
-
Here we are, a very brief overview of handles. What is a handle at heart? Well we can think back to C++, if you wish. When you design private member variables, do you want them exposed to the real world? No, so how do we interact with them? We implement methods right? A handle is a fairly similar approach if you will allow the metaphor to be stretched a little. Rather than allowing a piece of code or application to directly interact with an object, we instead implement handles to provide a means to access them. A handle can represent a thread, process, mutex, file, section object, etc. For more information please reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724457%28v=vs.85%29.aspx Please also reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724461(v=vs.85).aspx Note that when you close a handle to certain things like say a snapshot from CreateToolHelp32Snapshot it automatically cleans up the section allocation it made. Any time you want to read from a file, or a process, whatever, you need a handle. They are a critical part of the operating system and thus you can't hope to mod without them. Further posts will cover them in depth, but this is just to get you on the right track. I am actually in the process of starting the .ini system! Wee!
-
I might be interested in contributing as a regular team member, we'll have to see how things pan out.
-
Yes I know, WW just perplexes me with their design choice. Also this thread is not dead, I've just been busy with school and work. I will make a post soon covering handles I promise!
-
Right, but said cleanup would probably crash enthusiastically if the vector doesn't contain allocated heap addresses but just bare ints. Hence the two types. Then I would just call it a weird array wannabe vector.
-
Every C++ vector implementation I've seen cleans up it's allocations once the destructor is called. That's just normal implementation, as for their fixed length stuff, it could be a compiler optimization although I find that difficult to believe.
-
Eh. There are tons of RTS clones around. As long as they don't touch EA's intellectual property there's no issue there. Though, this is a forum of hackers and gamers... not sure they'll find any game designers here. Reporting in. OP may want to consider a simple C&C mod to build a viable team with first. Then work outwards.
-
I might make a post investigating this, it won't be fully in depth just enough to get the ball rolling because I still have to cover handles and start explaining how to implement an ini system. As tempted as I am to use existing tools for the job, I would rather write my own so everything fits together neatly. I've even considered github for the whole ordeal so people can contribute.
-
Visceroids should explode in a nuclear fireball. For the record you're correct, but other animations also do damage as well, so don't forget that.
-
Last time we messed around we changed the projectile of the obelisk. That's pretty neat, but we could've just changed the animation to get the nuke, or ion cannon or any number of effects we want. All I will say about that is modify the laser entry and change index 39 accordingly it's a byte folks. Experiment to see what happens, it's rather curious and funny at the same time. Why no tutorial? Because if you've been following along, you should be able to do it by yourself. We will cover handles soon, and then we'll start talking about how to actually add ini support so we can mod this game into oblivion. Questions and useful comments are always welcome.
-
That's because the 0xE8, 0xE9, 0x0F, and so on are relative calls/jumps, not calls/jumps which make use of modrm/sibs/displacements.
-
For the record, the Overrun option just stops tiberium from spawning and has nothing to do with growth and speed aside from spawning new tiberium. Why it's called overrun and not StopTiberiumSpread, beyond me. Ok so. In order to speed up the growth rate of tiberium we need the location of the growth(MapClass::RunLogic) function. It's located at: 0x004689F8 Now the important pieces relating to tiberium growth are as follows: CPU Disasm Address Hex dump Command Comments 00468A1D |. BA 1E000000 MOV EDX,1E This controls how many cells we iterate through. So 30 cells. Let's patch that to 256. Now it should look like: CPU Disasm Address Hex dump Command Comments 00468A1D BA 00010000 MOV EDX,100 Let the game run... Nothing? Tiberium doesn't even seem be affected by this... Or maybe we're missing something? Perhaps... CPU Disasm Address Hex dump Command Comments 00468B75 |. BD 01000000 MOV EBP,1 and CPU Disasm Address Hex dump Command Comments 00468B91 |> \C70424 02000000 MOV DWORD PTR SS:[LOCAL.13],2 Let's patch both of these to 16 cells and see what happens... CPU Disasm Address Hex dump Command Comments 00468B75 BD 10000000 MOV EBP,10 CPU Disasm Address Hex dump Command Comments 00468B91 \C704E4 10000000 MOV DWORD PTR SS:[ESP],10 Now we're getting somewhere, stuff is growing much faster, but we want a tiberium world here, so let's go to 256. Annnd... there we go. There's several tricks to make it instagrow to 12, and make concrete walls spawn tiberium, etc, and even make tiberium spawn whatever you can think of. As far as harvester bail counts are thus concerned: CPU Disasm Address Hex dump Command Comments 00436B55 |. BB 1C000000 MOV EBX,1C CPU Disasm Address Hex dump Command Comments 004BA430 |. B8 1C000000 MOV EAX,1C Keep in mind you are limited to 255 bails, unless of course you patch the code. Oh and boys and girls, this does affect the computer. So even if you gave him just a blossom tree and 1 harvester, well it balances itself out nicely.
-
Just check the map logic. 005D1230 800D A3E45300 04 OR BYTE PTR DS:[53E4A3],04 No tiberium on maps and won't spawn, which is cute and interesting at the same time. CPU Disasm Address Hex dump Command Comments 0048F42B |> \F605 A3E45300 04 TEST BYTE PTR DS:[53E4A3],04 sorta ontopic I think we'll cover the bail count next and why it's clamped to 28 and how to increase it so you too can be hood rich and thus acquire street cred like Kane did when he made Tiberium based bling.
-
For the fun part, I'd like the community to input. I've messed around with building tiberium, making tiberium instagrow to 12, etc. I just haven't picked a good avenue to demonstrate some of what we've learned.
-
Thread time. About time no? Maybe we'll play around a bit more after this post. So what is a thread? A thread is simply a unit of execution consisting of instructions. It is managed by the OS scheduler. Every process must have at least 1 thread. A thread is scheduled to run for a time slice. Typically that is 20-40ms. Understand this is different from multi-threading in which you have more than 1 physical cpu core, eg 2 cpus executing 2 threads. In fact an effective scheduler with only one cpu with effectively written code on the portion of the programmer can out perform an application which has 4 cpu cores and 4 threads to work with at any one time. I wonder why we don't focus more on the scheduling of threads and efficiency of our code instead of throwing more cores at the problem? Considering that multi-threading sometimes only adds a 20-30% boost in overall speed... Let's move on shall we? Threads can have their priority set. What this means is we are instructing the scheduler that our thread is more important than another so it's more likely to run in lieu of another thread. That means more time slices for us to work with. http://msdn.microsoft.com/en-us/library/windows/desktop/ms686277(v=vs.85).aspx Each thread has an ID associated with it, it's thread ID, which is unsigned long as well as guess what? A handle. Threads can also have their own storage ( TLS ) in the process which they store variables. Threads are also associated with their parent process. http://msdn.microsoft.com/en-us/library/windows/desktop/ms686749(v=vs.85).aspx Threads can also be suspended and resumed, and their context set. What is a context? A context is a stored data structure containing all the pertinent details about the thread at the point which it was queried. Things such as the status of it's registers, last error and so on. You can suspend a thread and redirect the EIP to resume execution somewhere else. Please reference earlier in the post where we talked about the debugger pane with the registers to get a better grasp of the context. Along with these links below: http://msdn.microsoft.com/en-us/library/windows/desktop/ms679362(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/windows/desktop/ms679284(v=vs.85).aspx When a thread is suspended obviously it doesn't run. http://msdn.microsoft.com/en-us/library/windows/desktop/ms686345(v=vs.85).aspx And to resume it we would call: http://msdn.microsoft.com/en-us/library/windows/desktop/ms685086(v=vs.85).aspx Naturally threads can be terminated, there are several ways to go about that. Please reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686724(v=vs.85).aspx Threads can also "spin" that is waiting to acquire access to a resource or a certain condition or set of to be met, ie through a lock or such. We'd use something like: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx Or better yet... http://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx Bare in mind Sleep merely instructs the scheduler not to schedule the specified thread to run for period X. WaitForXObject is used to tell us if an object is signaled or not. We will cover handles soon as that is a very large post unto itself. Handles to files, processes, threads, locks, windows, etc. That's all I can think of off the top of my head for now, I'll probably read over this post some more and edit it if I see any glaring errors.
-
I know I said I wanted to discuss threads and handles, but as I recalled, being able to read the documentation on sandpile, intel/amd manuals and x86ref is pretty important, what I am going to cover is how to interpret a key piece of this. http://ref.x86asm.net/geek32-abc.html FF 2 CALL r/m16/32 Call Procedure FF 3 CALLF m16:16/32 Call Procedure FF 4 JMP r/m16/32 Jump FF 5 JMPF m16:16/32 Jump FF 6 PUSH r/m16/32 Push Word, Doubleword or Quadword Onto the Stack Ok so FF is our opcode right, and the mneonic is pretty obvious, as is the description. BORING! But we have these strange numbers, 2, 3, 4, 5, and 6, what are they for? Look in the manuals and you'll see /2, or /3, etc. They tell you how to encode the modrm for that instruction. Skip to the end of the page where you see 32 bit ModR/M Byte Notice this: (In decimal) /digit (Opcode) 0 1 2 3 4 5 6 7 hmm... now match with the row/column. That's how you intrepret it folks. Really simple I hope. So to recap, if you see FF /2 You know that you're dealing with CALL r/m16/32. The acceptable modrm values are: 0x10->0x17, 0x50->0x57, 0x90->0x97, 0xD0->0xD7. Remember if you set the least significant bits to 4, you are telling the cpu a sib byte follows ( or if mod is 11, you use ESP ), and if you set it to 5, you are telling it you want to use displacement addressing ( or EBP if mod is not 0 ). In x64 it's rip-relative addressing instead of displacement only addressing. Remember the links I posted earlier exactly clarify these rules. I think unless anybody requests help on the SIB bytes which I believe are extremely self explanatory we will cover those. For now read over and enjoy.
-
Updated the post to include examples to understand modrm/sib bytes, and links detailing these in detail. I will add more material as I decide what topics need to be covered. Next post will touch on threads, handles, and other OS concepts and CompSci concepts. For the record I find modrm and sib to be the most complicated and nuanced topics to discuss because without a firm understanding of bitmasking and playing around with different combinations, it's difficult to understand. If you can grasp these concepts, then anything else I throw at you is pie.
-
C&C Story in a nutshell (Tiberium Universe) (WIP)
peterthepigeon replied to fir3w0rx's topic in C&C 1
What happened when Kane discovered tiberium. -
So we had fun right? Those parlor tricks were neat no? Thats peas compared to the power of what you can do. For now however, we need to get back to learning, but I hope it inspired you to dig and learn on your own in addition to what I've been posting here. Let's learn how to encode a x86 instruction shall we? So everybody and his grandma knows that a x86 instruction has a few parts prefix(es) opcode opcode2 modrm sib relative displacement immediate There are a total of four prefixes, lock prefix/repeat, segment override, and 2 size override prefixes. Your lock and repeat prefixes start at 0xF0 -> 0xF3, excluding 0xF1. Your segment overrides: #define PREFIX_SEGMENT_CS 0x2e #define PREFIX_SEGMENT_SS 0x36 #define PREFIX_SEGMENT_DS 0x3e #define PREFIX_SEGMENT_ES 0x26 #define PREFIX_SEGMENT_FS 0x64 #define PREFIX_SEGMENT_GS 0x65 Your size overrides are 0x66 and 0x67. 0x66 overrides the operand size 0x67 overrides the address size. We could discuss the opcode/opcode2, but I feel that it's wiser to save it for another time. Let's move onto the modrm and sib now. How do we intrepret the modrm and sib? Well think back to the first tutorial, remember I stressed how important understanding bitmasking was? Well here is why. http://pdos.csail.mit.edu/6.828/2006/readings/i386/fig17-2.gif Notice the register is packed into the byte using 3 bits, with the least most significant bit specifying if it is a register or a memory operation. The most significant bits, bits 6 & 7 is the mode. The SIB is largely self explanatory, where bits 6-7 specify the scale, 1, 2, 4, 8. The index and the base are registers usually, otherwise it could happen to be the displacement. Seem familiar and visible from the last tutorial? I hope so. We use the relative when doing calls/jumps. We'll cover this in the future. The displacement can be a memory address or an offset from a memory address. The immediate can be any value, 8 bit, 16 bit and 32 bit thereof. The only nuance I can recall about 64 bit is that aside from the rex prefix, the only difference is that the immediates are 64 bit whereas displacements/relatives are stuck to 32 bit. x64 also features rip-relative addressing. I'll edit this post to give a few nice examples of this so it's easier to comprehend. http://www.c-jump.com/CIS77/CPU/x86/X77_0090_addressing_modes.htm http://www.c-jump.com/CIS77/CPU/x86/X77_0060_mod_reg_r_m_byte.htm http://www.c-jump.com/CIS77/CPU/x86/X77_0100_sib_byte_layout.htm 77995FEE | FF 94 D8 EF BE AD DE | call dword ptr ds:[eax+ebx*8-21524111] | 77995FEE | FF A0 EF BE AD DE | jmp dword ptr ds:[eax-21524111] | 77995FEE | FF A4 D8 EF BE AD DE | jmp dword ptr ds:[eax+ebx*8-21524111] | 77995FEE | FF A4 0F EF BE AD DE | jmp dword ptr ds:[edi+ecx-21524111] | 77995FEE | FF 14 C5 EF BE AD DE | call dword ptr ds:[eax*8-21524111] | 77995FEE | FF 15 A8 0E 00 00 | call dword ptr ds:[EA8] | 77995FEE | FF 10 | call dword ptr ds:[eax] | 77995FEE | FF 17 | call dword ptr ds:[edi] | 77995FEE | FF 20 | jmp dword ptr ds:[eax] | 77995FEE | FF 27 | jmp dword ptr ds:[edi] 77995FE8 | FF 24 90 | jmp dword ptr ds:[eax+edx*4] | 77995FE8 | FF 24 D0 | jmp dword ptr ds:[eax+edx*8] | 77995FE8 | FF A4 D0 EF BE AD DE | jmp dword ptr ds:[eax+edx*8-21524111] | 77995FE8 | FF 24 D5 EF BE AD DE | jmp dword ptr ds:[edx*8-21524111] | 77995FDE | FF A2 EF BE AD DE | jmp dword ptr ds:[edx-21524111] | For all the examples above, modrm is after the FF opcode, INSTR_FAR_PREFIX. You'll notice I chose an easy displacement, 0xDEADBEEF, and the sib always comes before the displacement, and after the modrm. Play around with bitshifting and the links above, get a feeling for what's going on. This is critically important especially if you're tracing blocks and trying to deobfuscate/register swap or determine jumptables, etc.
-
You missed the entire point of the exercise. Nothing gets them excited to learn quite like seeing what you can do with the game. Fixing game bugs and adding features will be covered in future tutorials, and consider this is an intro to modding/hacking. What I've shown is perfectly in the bounds of that.
-
Alright enough learning, for now, let's have a little fun first. Just follow my lead and we'll get that obelisk shooting down aircraft and shooting across the map in no time, heck let's even throw in another parlor trick, we'll make it shoot nukes. Lotsa fun no? We'll go over every step of this later so you'll learn the concepts so you understand what is happening here. First let us understand the difference between hot and cold patching. Hot patching is modifying the executable in memory but not committing the changes to disk, thus not overwriting the original file. Cold patching is modifying the executable and committing the changes to disk overwriting the original file. AG is supposed to be AA, but I mistyped, and I'm only adding this here as a forewarning, I may fix this in the future. Start your game up. Now attach Ollydbg. Press F9 to run the program. Now press alt and e to get to executable modules and select C&C95. Press enter. If it goes back to ntdll, repeat the process over. You should see. Right click and look for search for, then all referenced strings. Note: Ollydbg 1.10 for some reason burps if you try to do this I haven't bothered investigating as using 2.0 works just fine. You should see. Press ctrl f and search for laser. You should see. This is the projectile used by the obelisk. Now I labelled a few things for our convenience. Note olly kinda messed up the comments I made. We have 2 methods for modifying the obelisk. I'm going to go ahead and explain method 1. Modify the AG entry to push 1. With the line selected, press spacebar, and type push 1, then click enter. You're done, save the modifications to disk and restart C&C95. BACKUP YOUR C&C BEFORE YOU DO THIS. Right click edit, Copy to Executable, then either right click save file, or click the big red x, and follow through. Method 2 is harder. Now we're going to modify the actual entry in the array where it's stored. I'm going to cut some corners here to shave some time explaining things and go ahead and hand out where the array is in memory. 004B62FD |. 8B1495 BC295000 MOV EDX,DWORD PTR DS:[EDX*4+5029BC] To access the laser entry we simply do the following: Take the index we found for the laser which is 0xC. then: 0xC * 4 + 0x5029BC. Ok so we've done the math, you should have 0x5029EC. Press ctrl and g in the hex pane and paste that address. You should see. Note I surrounded it with a big red box. Then we reverse the endian-ness to get. 0x531A60. Ctrl and g again in the hex pane and go to that address. You should see. Big red box again. Follow my lead exactly. See the 1101? Change that to 1109 Selec the 01 by clicking on it. Press ctrl e, then type 09. Press ok. Congratulations, now your obelisk can shoot air targets. Now we're going to modify the range of the obelisk and some other attributes, note, we will not be cold patching for this one. We're just going to follow the same steps above. I'm going to provide you the address you need. The index for the Obelisk's weapon is 20, converted to hex 0x14. 0044114A |. 8A84C1 D834500>MOV AL,BYTE PTR DS:[ECX+EAX*8+5034D8] To get to the obelisk, we need to: address = 0x14 * 8 + 0x14 + 5034D8 You should have 0x50358C. Press ctrl g and paste that address and press enter. You should see. If you want to have your obelisk shoot nukes, change the 0xC ( Lasershot Projectile ) to 0xE ( AtomicDn Projectile ), by clicking on it, ctrl and e, change to 0xE enter. Hahaha, just be careful. The damage is 0xC8, so you should change to 0xFF, follow above. The rate of fire is 0x5A, but because of the way the game treats the obelisk/laser, well you're limited to how fast you can fire, to set the fire rate to 0, you'd set it to 0xFD causing an overflow because the game adds 3 to the rate of fire. There is a way to fix the obelisk so it can fire nice and fast, but that's for another time perhaps. The range of the weapon is 7 cells, to a maximum of the map size. So set it say to 30 cells, 0x1E or something. And that's it. Pick under siege c&c. Sell a couple of units on the repair bay and whatever you need so you can build an obelisk. Build yourself a power plant or 2 and the obelisk and enjoy the fruits of your labor. Note: If you changed the projectile to AtomicDn it won't be able to shoot down those pesky A-10s or Orcas, I challenge you to fix that yourselves and while you're at it, change the speed of the projectile from 0x64, to 0xFF ( instant ) Whew that was a lot wasn't it? Questions/Comments?