
Reverse Engineering Challenges - luu
http://challenges.re/
======
isido
This site and accompanying book
([http://beginners.re/Reverse_Engineering_for_Beginners-
en.pdf](http://beginners.re/Reverse_Engineering_for_Beginners-en.pdf)) seem a
nice effort. Briefly reading the book, it seems that you need to be an
intermediate or advanced beginner, or know something about assembly
beforehand.

Some terms (opcode, ISA) are not really explained (except in the glossary)
before they are used and there are perhaps too much detail in the expense of
the bigger picture.

Criticisms aside, the book and the challenges seem interesting and the efforts
of the author must be appreciated!

~~~
tptacek
Get past the idea that you need to be advanced to grok assembly language.
Assembly is in a lot of ways _easier_ than a lot of higher-level languages.
When I was growing up in the early 90s, a lot of my friends started on x86
assembly as a first language --- and x86 is the most annoying instruction set
to learn.

The right way to learn this stuff is to dive in. You'll be over your head for
a few hours, but you'll get your bearings. There are topics this technique
doesn't work great with, but assembly reversing isn't one of them.

An additional benefit: assembly is one of those things that you might not use
all the time in your career (although I've ended up using it quite a bit), but
that will nonetheless illuminate lots of other things about computer science.
There's a reason Knuth used it as a language to express algorithms in TAOCP.

I can sum up the core idea of assembly for you in just a few sentences:

* You're given 8-32 global variables of fixed size to work with, called "registers".

* Virtually all computation is expressed in terms of simple operations on registers.

* Real programs need many more than 8-32 variables to work with.

* What doesn't fit in registers lives in memory.

* Memory is accessed either with loads and stores at addresses, as if it were a big array, or through PUSH and POP operations on a stack.

* Memory is to an assembly program what the disk is to a Ruby program: you pull things out of memory into variables, do things with them, and eventually put them back into memory.

* Control flow is done via GOTOs --- jumps, branches, or calls.

* A jump is just an unconditional GOTO.

* Most operations on registers, like addition and subtraction, have the side effect of altering status flags, like "the last value computed resulted in zero". There are just a few status flags, and they usually live in a special register.

* Branches are just GOTOs that are predicated on a status flag, like, "GOTO this address only if the last arithmetic operation resulted in zero".

* A CALL is just an unconditional GOTO that pushes the next address on the stack, so a RET instruction can later pop it off and keep going where the CALL left off.

Everything else is just a detail.

When working with assembly, a lot of people will just get the programmer's
reference manual for the instruction set in a PDF (they're published for
free). Here's a short one for X86:

[http://ref.x86asm.net/coder32.html](http://ref.x86asm.net/coder32.html)

Here's ARM:

[http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001m/QR...](http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001m/QRC0001_UAL.pdf)

Here's AVR:

[http://www.atmel.com/images/atmel-0856-avr-instruction-
set-m...](http://www.atmel.com/images/atmel-0856-avr-instruction-set-
manual.pdf)

Even if you'd never written a line of assembly, if I asked you to express the
procedures of a simple Ruby program in assembly and gave you the instruction
set reference and those sentences, you would figure out how to get the job
done in a couple hours. No monads or linear algebra required!

~~~
tptacek
Hm. 12 sentences. Someone here can do it better in fewer sentences, I think.

~~~
lunixbochs
Much of assembly programming is variants of these commands:

    
    
        - mov <dst>, <src>            | dst = src
        - sub <dst>, <src a>, <src b> | dst = a - b
        - jump <label>                | continue running at <label>
        - jump if equal <label>       | continue running at <label> if both sources of
                                        the last command were equal
        - call <label>                | save the current location, then continue
                                        running at <label>
        - ret                         | continue running after the previous CALL
                                        instruction
    

<dst> can be:

    
    
        - any memory address
        - any of 8-32 available temporary integer variables called "registers"
    

<src> can be any valid <dst> or a hardcoded integer known as an "immediate"

~~~
tptacek
This is both more detailed than mine and uses fewer sentences. My only nit is
that I feel like understanding status flags is really important.

~~~
lunixbochs
I had several nitpicks with mine, but realized once the learner starts asking
questions about gaps they're in a pretty good place to find an answer on their
own.

I do agree flags is less obvious, but also takes a bit of space to list what
kind of flags one might see:

"jump if equal" is facilitated by an implicit "flags" register which is set
after most arithmetic or comparison operations like "sub". Possible flags
include:

\- carry: the last arithmetic operation overflowed

\- zero: result of the last operation was zero

\- parity: result of the last operation was odd

\- sign: result of the last operation was negative

------
johnernaut
Although probably not well-known, [http://crackmes.de/](http://crackmes.de/)
is a site I've been using to create / upload and also work on challenges for
various RE applications for about 10 years now. I'd definitely recommend it to
newcomers wanting to learn more about RE in general.

------
w23j
My Sophos Anti-Virus blocked this site, mentioning a 'Mal/HTMLGen-A' on it.

