So, recently I've been doing a lot of stuff. Mainly concerning reverse engineering, but I was feeling a bit off. I decided it's time for a change. Since after all, I don't even have the time to watch a movie longer than thirty minutes, not saying anything about playing a game, I thought it's going to be a good idea to ship myself over the linux system. I've chosen Ubuntu, because the time when I had a patience to configure everything in my PC from the bottom-up passed... and it's looking great. After that, I've set up my environment. Got my browser, social communicators ready, checked the compilers, and I started looking for my new code editor (since notepad++ doesn't work in here). I thought about Vim. I gave it chance not so long ago but it didn't fit me. Didn't know why, because it has thousands of positive opinions and it's highly customizable. Now I do. Jumping into such a complicated application right from where you're standing is a terrible idea. I mean, first version of vim was actually running in a console environment. No mouse, no fancy looking windows, no beautiful colors, just black background and some text. It takes some time to learn all the commands, all the hotkeys to even think about staying with Vim. This time I decided to take it slow. I've done vimtutor, read some manual, wrote a simple cheat sheet on paper with all the useful commands and keys, did a bit(!) of configuration, and I still felt that something is terribly wrong. I realized that I was using gVim... Yeah, you might think, "What's the difference?". The answer is, "This is not how vim was intended to be used!". I've switched to the terminal, and you know what? Now I feel like at home. Everything is lean and clean. A bit of transparency to my console window, some graphical tweaks, and voila! Couldn't live without it.
The thing about Vim is that everything you do, you can do without taking your hands of the keyboard. That's simply amazing. Most of the code editors I've been using were aimed at regular people, who didn't have time, nor patience to remember all the hotkeys or commands an application could offer them. So I had to spent half of my time looking for certain editor functions in menu. Now I don't. I've got everything I need in one place. Want to turn something on? Sure, go ahead, type it! Want to make something permanent? Open your configuration file (with edit $MYVIMRC) and type it. That's amazing how it boosts productivity.
My advice to anybody who wants to use Vim: Take your time.
Lazy Coding
Friday, February 22, 2013
Sunday, January 20, 2013
DLLExport with naked functions.
Not so long ago I've read a blog post written by Gynvael Coldwind about creating naked functions in C/C++ with MinGW compiler on x86 platform. He pointed out, that GCC is not supporting naked attribute on platforms other than ARM, AVR, IP2K and SPU. So basically, if you'd like to generate header-less function, you'd be stuck. But a method presented by Gynvael Coldwind works, and it works pretty flawlessly. But what if we want to export one naked function? Definition of the function is provided in the header file, but the proper declaration header is... not generated by the compiler, and has to be written by us. So we have to provide a proper information for the linking process. What's the solution then?
Looking into asm code generated by GCC, we can clearly see, that function generated with __declspec(dllexport) has an additional section called drectv, just under it's body:
Which is added specifically for the linker, so pointed function can be included in the export table.
Of course, function name depends on the case. Changing call convention, adding function arguments (if using __stdcall), function decorations in C++, etc. so we have to type the proper function name as the export symbol.
Below you can find the source code for that method:
Source Code
.globl _returnfive _returnfive: push ebp mov ebp, esp mov eax, 0x5 pop ebp ret .section .drectve .ascii " -export:\"returnfive\""
Looking into asm code generated by GCC, we can clearly see, that function generated with __declspec(dllexport) has an additional section called drectv, just under it's body:
.section .drectve .ascii " -export:\"returnfive\""
Which is added specifically for the linker, so pointed function can be included in the export table.
Of course, function name depends on the case. Changing call convention, adding function arguments (if using __stdcall), function decorations in C++, etc. so we have to type the proper function name as the export symbol.
Below you can find the source code for that method:
Source Code
Sunday, October 21, 2012
Binary files, creating your own file format.
At first, to understand this post, you
have to know basic binary operations and a bit of C++ language. You
do? Cool. Let's roll.
What?
That kind of file is not designed for being read by text-editors. Of course, there's
no problem with it. A bit advanced editors would open binary file but
believe me, you won't see anything useful. Not because it's encrypted
or protected by some kind of password. It's just, they are nothing
more than a sequence of bytes, written one by one, most of the time
grouped in blocks. How they are grouped, well, that depends of the
file format.
Why?
Mostly, because of
it's efficiency. If you have a scheme of the file format, you can
write an application that will read the file and get it's
information. They are much lighter than their text represented
alternatives. String occupy much more space in the memory than lean
numbers, and the information you want to store is not always a text.
Sometimes it's a content of an archive or an *.exe file. That kind of
data was not meant to be read by people, but by machines, so it would
be a big misunderstanding if we would even try to store that kind of
information as a string.
How?
Well, there are
two ways of creating your own file format. The first one is to grab
some data and write a file with it, using a binary mode. It's fast,
it's efficient, but at the same time, very chaotic and problematic.
Reasons?
- If you have more of those files, how would you know that what you are trying to read is your file format?
- How will you distinguish different version of your file format? Application using older version may not be able to read your data properly, leading to major problems.
- Writing a binary data without proper informations describing your file format will mislead other applications, which may to lead to data corruption.
The second way of
creating a binary file format is to break your format into sections.
The first one, should be file format header, containing unique
signature and proper version of your file format. Such a simple
action and it's solving all of the problems I mentioned before. File
format signature prevents mistakes while loading wrong files. Version
of your file format lets you control the different kinds of files
you'll try to load into you application. Depending on kind of
information you want to store, you'll have to create more sections
containing important data.
Example of an application writing and reading in binary mode.
Example of an application writing and reading in binary mode.
#include <iostream> #include <fstream> struct FHeader { char signature; int version; }; struct FData { int number; char sign; bool state; }; struct FContainer { FHeader header; FData data; }; int main() { FContainer in_container; FContainer of_container; of_container.header.signature = 'R'; of_container.header.version = 0x1; of_container.data.number = 5; of_container.data.sign = 'A'; of_container.data.state = false; std::ofstream output_stream("file.bin", std::ios::binary); output_stream.write(reinterpret_cast<const char*>(&of_container), sizeof(of_container)); output_stream.close(); std::ifstream input_stream("file.bin", std::ios::binary); input_stream.read(reinterpret_cast<char*>(&in_container), sizeof(in_container)); input_stream.close(); std::cout << in_container.header.signature << std::endl; std::cout << in_container.header.version << std::endl; std::cout << in_container.data.number << std::endl; std::cout << in_container.data.sign << std::endl; std::cout << in_container.data.state << std::endl; }
Subscribe to:
Posts (Atom)