Courtesy of reverser's page of reverse engineering
Well, Edi found the encryption routine and writes: "it took me 2 hours only to UNDERSTAND what is done in 30 lines of assembler... everyone should study this compact code, it was real tasteful :-)" I agree completely with him, in fact I believe we should now slowly proceed (say before the end of September :-) to the 'real' task: reversing the encryption routines used by our stegonating targets!

stego
Back to Advanced Steganography

Edi to reverser+: 26 March 1998

Edi:

Dear reverser+,

First of all I want to thank you for setting up such nice "gates"
to advanced pages. Every one of the 3 was great fun, and they showed
me a important thing:

You can do everything if you just try hard enough!

I found the advanced steganography page. I don't think
it would have been possible without the help you provided on the
starting page, especially without Flynn's light version I wouldn't
write this now. After studying the text I thougt I just need a
working bruteforcer to crack the steganos encrypted file.

But I had to work more: first of all, the file offsets were wrong,
so I had to reverse engineer steganos again, on my own. I found
the encryption routine (it took me 2 hours only to UNDERSTAND what
is done in 30 lines of assembler... everyone should study this
compact code, it was real tasteful :-) and wrote my own bruteforcer,
first in Pascal, which was way too slow, then in C, too slow again,
and finally I decided to write it in assembler. When you have to
try 26^8 possible keys, you need to have
1.) a fast machine
2.) a good and fast algorythm to check the keys

I don't have #1, so I made #2. And the only way to achieve this is
programming in assembler. My program is not perfect, there must 
still be ways left to speed it up somewhere, but it works fine for me
now (I had to correct several fatal bugs in the past few days :)
Started it in the evening, I came back in the morning and guess what,
I saw the right key!

Have a look at this self-explaining (I hope) program. You have
to know the file name to use it, but a check to see if you get
a filename is easy to implement.
---- start of brute.asm --- brute segment para 'CODE' org 100h assume cs:brute, ds:brute, es:brute, ss:brute start: jmp init start_message db '[start]',13,10,'$' end_message db '[end]',13,10,'$' to_decode db 12 dup (0) found db 'Found a key: $' passwd db 8 dup ('a') db 13,10,'$' xorvals db 8 dup (0) key db 256 dup (0) filehandle dw 0 key_stage1 db 256 dup (0) filename db 'adva.sef',0 x db 0 y db 0 cte db 0 counter dw 0 start1 equ 's' start2 equ 'a' start3 equ 'a' start4 equ 'a' start5 equ 'a' start6 equ 'a' start7 equ 'a' start8 equ 'a' main proc near mov ah,09h mov dx,offset start_message int 21h mov ah,3dh mov al,10000000b mov dx,offset filename int 21h ; open file mov [filehandle],ax mov bx,ax mov ah,42h mov al,0 mov cx,0 mov dx,019h int 21h ; seek to 0x19h mov bx,[filehandle] mov ah,3fh mov cx,12 mov dx,offset to_decode int 21h ; read encoded filename (max. 12 chars) mov ah,3eh mov bx,[filehandle] int 21h ; close file cld xor al,al mov di,offset key_stage1 @prepare_stage1: stosb inc dx inc al jnz @prepare_stage1 xor dl,dl mov byte ptr [offset passwd], start1-1 @loop_1: inc byte ptr [offset passwd] mov dh, byte ptr [offset passwd] mov byte ptr [xorvals],dh xor dl,dh mov byte ptr [offset passwd+1],start2-1 @loop_2: inc byte ptr [offset passwd+1] mov dh, byte ptr [offset passwd+1] shl dh,1 mov byte ptr [xorvals+1],dh xor dl,dh mov byte ptr [offset passwd+2],start3-1 @loop_3: inc byte ptr [offset passwd+2] mov dh, byte ptr [offset passwd+2] shl dh,1 add dh, byte ptr [offset passwd+2] mov byte ptr [xorvals+2],dh xor dl,dh mov byte ptr [offset passwd+3],start4-1 @loop_4: inc byte ptr [offset passwd+3] mov dh, byte ptr [offset passwd+3] shl dh,2 mov byte ptr [xorvals+3],dh xor dl,dh mov byte ptr [offset passwd+4],start5-1 @loop_5: inc byte ptr [offset passwd+4] mov dh, byte ptr [offset passwd+4] shl dh,2 add dh, byte ptr [offset passwd+4] mov byte ptr [xorvals+4],dh xor dl,dh mov byte ptr [offset passwd+5],start6-1 @loop_6: inc byte ptr [offset passwd+5] mov dh, byte ptr [offset passwd+5] shl dh,3 sub dh, byte ptr [offset passwd+5] sub dh, byte ptr [offset passwd+5] mov byte ptr [xorvals+5],dh xor dl,dh mov byte ptr [offset passwd+6],start7-1 @loop_7: inc byte ptr [offset passwd+6] mov dh, byte ptr [offset passwd+6] shl dh,3 sub dh, byte ptr [offset passwd+6] mov byte ptr [xorvals+6],dh xor dl,dh mov byte ptr [offset passwd+7],start8-1 @loop_8: inc byte ptr [offset passwd+7] mov dh, byte ptr [offset passwd+7] shl dh,3 xor dl,dh cmp dl,08ah ; checksum of pw jne @bad_key call prepare_key call decode ; we know the filename, so why not cmp al,'a' ; implement it into the code :-? jne @bad_key call decode cmp al,'d' jne @bad_key jmp @checkit ; few filenames will start with ; 'ad', so time doesn't really ; matter here. We need to put the ; check for the next chars elsewhere ; because of the relative jumps below... @good_key: call printpass @bad_key: xor dl,dh cmp byte ptr [offset passwd+7],'z' jb @loop_8 xor dl, byte ptr [xorvals+6] cmp byte ptr [offset passwd+6],'z' jb @loop_7 xor dl, byte ptr [xorvals+5] cmp byte ptr [offset passwd+5],'z' jnb @loophelp_6 jmp @loop_6 @loophelp_6: xor dl, byte ptr [xorvals+4] cmp byte ptr [offset passwd+4],'z' jnb @loophelp_5 jmp @loop_5 @loophelp_5: xor dl, byte ptr [xorvals+3] cmp byte ptr [offset passwd+3],'z' jnb @loophelp_4 jmp @loop_4 @loophelp_4: xor dl, byte ptr [xorvals+2] cmp byte ptr [offset passwd+2],'z' jnb @loophelp_3 jmp @loop_3 @loophelp_3: xor dl, byte ptr [xorvals+1] cmp byte ptr [offset passwd+1],'z' jnb @loophelp_2 jmp @loop_2 @loophelp_2: call printstat ; show the user how much is left xor dl, byte ptr [xorvals] cmp byte ptr [offset passwd],'z' jnb @loophelp_1 jmp @loop_1 @loophelp_1: mov ah,09h mov dx,offset end_message int 21h mov ax,4c00h int 21h main endp @checkit: call decode cmp al,'v' jne @checkit_bad_key call decode cmp al,'a' jne @checkit_bad_key call decode cmp al,'.' jne @checkit_bad_key call decode cmp al,'t' jne @checkit_bad_key call decode cmp al,'x' jne @checkit_bad_key call decode cmp al,'t' jne @checkit_bad_key jmp @good_key @checkit_bad_key: jmp @bad_key printstat proc near push dx mov ah,09h mov dx,offset passwd int 21h pop dx ret printstat endp printpass proc near push dx mov ah,09h mov dx,offset found int 21h mov ah,09h mov dx,offset passwd int 21h pop dx ret printpass endp decode proc near xor ah,ah mov al, [x] ; al = x inc ax xor ah,ah mov di, offset key add di, ax xor bh, bh mov bl, [y] ; bl = y add bl, [di] xor bh,bh mov di, offset key mov si, di add di, ax add si, bx mov ch, [di] mov cl, [si] mov [di], cl mov [si], ch mov byte ptr [x], al mov byte ptr [y], bl add byte ptr [cte], 0dh add cl,ch ; cl = xorindex xor ch,ch mov di, offset to_decode add di, [counter] mov al, byte ptr [di] mov di, offset key add di, cx mov ah, [di] xor ah, [cte] xor al, ah inc byte ptr [counter] ret decode endp prepare_key proc near mov byte ptr [counter], 0 mov byte ptr [cte],028h mov byte ptr [x],0 mov byte ptr [y],0 mov cx,128 mov si,offset key_stage1 mov di,offset key rep movsw mov cx,0 ; cx=i xor ax,ax ; ax=old @prepare_key_loop: mov di, offset key add di, cx mov bl, byte ptr [di] add ax,bx mov bx, cx and bl, 7d add bx, offset passwd mov bl, byte ptr [bx] add ax,bx and ax, 000ffh mov di,offset key mov si,di add di,cx add si,ax mov bh,[di] mov bl,[si] mov [di],bl mov [si],bh inc cl jnz @prepare_key_loop retn prepare_key endp init: mov ah,4ah mov bx,offset end_ add bx,15 mov cl,4 shr bx,cl inc bx int 21h mov sp,offset end_ jmp main init_end label near dw (256-((init_end-init) shr 1)) dup (?) end_ equ this byte brute ends end start --- end of brute.asm ---

The above program checks every possible key. Let it run over night
like I did, go to bed and dream of reverser's next puzzle (I hope I
don't have to brute force it, I want to THINK :-)

Habi d'ere,
  Edi
(c) 1998 Edi All rights reversed

You are deep inside reverser's page of reverse engineering, choose your way out:

stego
Back to Advanced Steganography

redhomepage redlinks redanonymity +ORC redstudents' essays redacademy database
redtools redcocktails redjavascripts wars redantismut CGI-scripts redsearch_forms redmail_reverser
redIs reverse engineering legal?