d2jsp
Log InRegister
d2jsp Forums > Off-Topic > Computers & IT > Programming & Development > X64 Assembly
12Next
Add Reply New Topic New Poll
Member
Posts: 1,358
Joined: Dec 30 2012
Gold: 0.10
Feb 15 2013 01:03pm
I'm having trouble with correctly comparing the byte in a character array to a searched for character byte.

I'm new to this but I thought I was doing it right since my character array is in the register RCX.

When my program compares the byte register CL with the searched for byte stored in register DL it does not take the jump to ChangeChar even when they should be the same character in the iteration

IDK sorry if I did not explain very well but here's my code and hopefully someone will be able to help me out

Assembly.asm
Code
.data
ArraySize dd 0
NewChar byte '*'

.code
;String character replace code
CharReplace proc
cmp r8d, 0
jle LoopEnd

mov eax, 0
mov ArraySize, r8d
mov bl, NewChar

LoopStart:
cmp eax, ArraySize
jge LoopEnd
inc eax
cmp cl, dl         <----- here
je ChangeChar
add rcx, 1
jmp LoopStart

ChangeChar:
mov byte ptr[rcx], bl
add rcx, 1
jmp LoopStart


LoopEnd:
ret
CharReplace endp
end


main.cpp
Code
#include <iostream>
#include <conio.h>
#include <Windows.h>
#include <string>

extern "C" void CharReplace(void * arr, char, int size);

int main()
{
std::string s = "aakjflijafllwlieeaf";
int size = s.size();

char * cArray = new char[size];

for(int i = 0; i < size; i++)
{
 cArray[ i ] = s.at( i );
}

CharReplace(cArray, 'a', size);

for(int i = 0; i < size; i++)
{
 std::cout << cArray[ i ];
}

_getch();
delete [] cArray;
return 0;
}


Just prints the same thing twice.

Code
aakjflijafllwlieeaf


e/ Damnit.. Should have posted this in the C++ subforum owell lul

This post was edited by SelfTaught on Feb 15 2013 01:21pm
Member
Posts: 13,425
Joined: Sep 29 2007
Gold: 0.00
Warn: 20%
Feb 15 2013 01:43pm
this might help you a bit. its in a different syntax though and i made it for d2jsp crack me thread i made which is now dead but it should help you. i would personally use 3 registers. 1 for your std input from user or w/e, 1 for the character array and 1 for the size of the character array.

from there i would loop byte to byte xoring to check for like-ness of the two characters. although in my application i am simply displaying a message if the values are different or the same and exiting but the logic behind this would be if the values ARE the same to jump to a new label in which to do a char replace. (or even a asm function.)

since you would have the current position in the array you should be able to quickly goto that position and make a change. hopefully that helped you a bit.

if all else fails you can compile your C++ program and run objdump on it in linux to see its asm output


Code
.section .data

enter_pass:
.ascii "Enter the password\n\0"
password:
.ascii "abgirl"
.equ password_len, . - password
corr_pass:
.ascii "Password is right\n\0"
incorr_pass:
.ascii "Password is wrong\n\0"

.section .bss

.equ in_pass_size, 500
.lcomm in_pass, in_pass_size

.section .text

.global _start

_start:

movl $1, %ebx
movl $enter_pass, %ecx
movl $20, %edx
movl $4, %eax
int $0x80                            #linux print to stdout

movl $0, %ebx
movl $in_pass, %ecx
movl $in_pass_size, %edx
movl $3, %eax
int $0x80                         #linux get line stdin

movl $password, %ebx
movl $in_pass, %edx
movl $password_len, %ecx            #moving the values into the registers

loop:                                       #the checking loop (dont mind the registers this is 32bit but the logic is there (this is also at&t syntax so it looks a bit different)
movb (%ebx), %al                #move first byte of ascii array into %al (to be checked)
xorb (%edx), %al                 #xors the first entered  byte to the hard coded byte
cmpb $0, %al                        #if 0 is stored in %al (review xor and how it works if you dont understand why 0 is there)
jg incorr                                 #if the output is greater than 0 its incorrect (aka letters are different. you can change this line to jump to a label to do a replace then add a label after the jg call to jump back into the checking.)
inc %ebx                              
inc %edx                               #increase the position of the stdin input as well as character array
dec %ecx                              #decrease the length of the character array
cmpl $0, %ecx                       #if there are still bytes to be read
jg loop                                    #loop again (sicne we increased the addresses by 1 byte when the loop loops again it will be moving and checking the next bye in teh array)
jmp corr                                 #else if there is no bytes and we havent jumped to incorrect we are good.

incorr:
movl $1, %ebx
movl $incorr_pass, %ecx
movl $19, %edx
movl $4, %eax
int $0x80                           #print incorrect to stdout then exit
jmp return

corr:
movl $1, %ebx
movl $corr_pass, %ecx
movl $19, %edx
movl $4, %eax
int $0x80                         #print correct to stdout

return:
movl $0, %ebx
movl $1, %eax
int $0x80                               %linux exit


This post was edited by AbDuCt on Feb 15 2013 01:48pm
Member
Posts: 1,358
Joined: Dec 30 2012
Gold: 0.10
Feb 15 2013 03:20pm
Quote (AbDuCt @ Feb 15 2013 11:43am)
this might help you a bit. its in a different syntax though and i made it for d2jsp crack me thread i made which is now dead but it should help you. i would personally use 3 registers. 1 for your std input from user or w/e, 1 for the character array and 1 for the size of the character array.

from there i would loop byte to byte xoring to check for like-ness of the two characters. although in my application i am simply displaying a message if the values are different or the same and exiting but the logic behind this would be if the values ARE the same to jump to a new label in which to do a char replace. (or even a asm function.)

since you would have the current position in the array you should be able to quickly goto that position and make a change. hopefully that helped you a bit.

if all else fails you can compile your C++ program and run objdump on it in linux to see its asm output


Code
.section .data

enter_pass:
.ascii "Enter the password\n\0"
password:
.ascii "abgirl"
.equ password_len, . - password
corr_pass:
.ascii "Password is right\n\0"
incorr_pass:
.ascii "Password is wrong\n\0"

.section .bss

.equ in_pass_size, 500
.lcomm in_pass, in_pass_size

.section .text

.global _start

_start:

movl $1, %ebx
movl $enter_pass, %ecx
movl $20, %edx
movl $4, %eax
int $0x80                            #linux print to stdout

movl $0, %ebx
movl $in_pass, %ecx
movl $in_pass_size, %edx
movl $3, %eax
int $0x80                         #linux get line stdin

movl $password, %ebx
movl $in_pass, %edx
movl $password_len, %ecx            #moving the values into the registers

loop:                                       #the checking loop (dont mind the registers this is 32bit but the logic is there (this is also at&t syntax so it looks a bit different)
movb (%ebx), %al                #move first byte of ascii array into %al (to be checked)
xorb (%edx), %al                 #xors the first entered  byte to the hard coded byte
cmpb $0, %al                        #if 0 is stored in %al (review xor and how it works if you dont understand why 0 is there)
jg incorr                                 #if the output is greater than 0 its incorrect (aka letters are different. you can change this line to jump to a label to do a replace then add a label after the jg call to jump back into the checking.)
inc %ebx                              
inc %edx                               #increase the position of the stdin input as well as character array
dec %ecx                              #decrease the length of the character array
cmpl $0, %ecx                       #if there are still bytes to be read
jg loop                                    #loop again (sicne we increased the addresses by 1 byte when the loop loops again it will be moving and checking the next bye in teh array)
jmp corr                                 #else if there is no bytes and we havent jumped to incorrect we are good.

incorr:
movl $1, %ebx
movl $incorr_pass, %ecx
movl $19, %edx
movl $4, %eax
int $0x80                           #print incorrect to stdout then exit
jmp return

corr:
movl $1, %ebx
movl $corr_pass, %ecx
movl $19, %edx
movl $4, %eax
int $0x80                         #print correct to stdout

return:
movl $0, %ebx
movl $1, %eax
int $0x80                               %linux exit


Alright thanks. So try checking the two byte registers using XOR then if they're not equal continue the loop? I'll give this a shot and post back if I have any troubles.
Member
Posts: 13,425
Joined: Sep 29 2007
Gold: 0.00
Warn: 20%
Feb 15 2013 03:42pm
Quote (SelfTaught @ Feb 15 2013 05:20pm)
Alright thanks. So try checking the two byte registers using XOR then if they're not equal continue the loop? I'll give this a shot and post back if I have any troubles.


yea something to that effect.

store the first byte of the char array in one register
store first byte of the char you want to check against in another register
loop until end of char array or xor returns matching character (if xor returns 0 if both chars are the same)
if xor returns 0 jump to new label to replace that current character (your registers are already at the current char spot because your incrementing them byte by byte so simply just mov a new byte into it)
jump back to the check loop
loop until end of array

something like that. shouldnt be much different than the code i posted. but it seems it would be the simplest way.

you can also compare word for word (4 bytes aka a long) but its a bit tricky.

you can also skip the length of the array part and just check for 0x00 (nullbyte) either way works (you will have to append nullbyte to the end of all your strings or else you will start segfaulting from reading into some other memory). null byte may be more portable seeing as you dont need to count the char array size before hand so i suggest using it instead.

so to implement that just do i direct comparison to the current character in the array at the end of the loop

Code
movb (%ebx), %al  #not sure if you need to move the byte back into the register. xor might of overwritten it.
cmpb $0x00, %al
je array_finished


and if you find a nullbyte that means youre at the end of your string and you should exit

edit:: also if you are planning on keeping the original address to the character array i suggest moving its address to a new register to be modified so the original is untouched simply because its easier than trying to reset/find your starting address to the beginning of your string.

This post was edited by AbDuCt on Feb 15 2013 03:49pm
Member
Posts: 1,358
Joined: Dec 30 2012
Gold: 0.10
Feb 15 2013 07:14pm
How do you print to the windows console in assembly?

This post was edited by SelfTaught on Feb 15 2013 07:15pm
Member
Posts: 1,358
Joined: Dec 30 2012
Gold: 0.10
Feb 15 2013 07:42pm
Got it working. Here's the code

Changed cmp cl, dl with cmp byte ptr[rcx], dl and it works great :D

Code
.data
ArraySize dd 0
NewChar byte '*'

.code
CharReplace proc
cmp r8d, 0;Check if array size parameter is = 0
jle LoopEnd;Jump to end if true!

mov eax, 0
mov ArraySize, r8d
mov r9b, NewChar

LoopStart:
cmp eax, ArraySize
jge LoopEnd
inc eax
cmp byte ptr[rcx], dl
je ChangeChar

add rcx, 1
jmp LoopStart

ChangeChar:
mov byte ptr[rcx], r9b
add rcx, 1
jmp LoopStart

LoopEnd:
ret
CharReplace endp
end
Member
Posts: 13,425
Joined: Sep 29 2007
Gold: 0.00
Warn: 20%
Feb 17 2013 03:01am
good to hear you got that working.

meanwhile since there is an active asm topic here is a cool little trick that will mess with debuggers (and can be used to evade them)

try to figure out what breakpoint should be triggered and which wont before scrolling down

Code
.section .text
.globl _start
_start:
  jmp start
enter:
  pop %rcx
  inc %rcx
  jmpq *%rcx
detected:
  int3
start:
  call enter
detectbreak:
  push $0x3458cc6a
  int3
  jz detected


now lets follow program flow to what we think should be happening.

Code
.section .text
.globl _start
_start:
  jmp start         #(1)goto start
enter:
  pop %rcx          #(3)since we used call we can pop the return address off the stack
  inc %rcx          #(4)increase address +1
  jmpq *%rcx        #(5)jump to that address
detected:
  int3              #(10)never reached
start:
  call enter        #(2)goto enter
detectbreak:
  push $0x3458cc6a  #(6)push a hex string to stack
  int3              #(7)issue a breakpoint
  jz detected       #(9)shouldnt jump


what is actually happening

Code
.section .text
.globl _start
_start:
  jmp start         #(1)goto start
enter:
  pop %rcx          #(3)since we used call we can pop the return address off the stack
  inc %rcx          #(4)increase address +1 (our address we are actually jumping to is detectbreak +1
                    # so the initial push statement is jumped pass
  jmpq *%rcx        #(5)jump to that address
detected:
  int3              #(10)breakpoint is now hit
start:
  call enter        #(2)goto enter
detectbreak:
  push $0x3458cc6a  #(6)push a hex string to stack (we skipped the push though so we are now execing byte code
  #    0x6a 0xcc 0x58 0x34 0xCC
  #    Translation:
  #    0x6a 0xcc             pushb $0xcc
  #    0x58                  pop %rax
  #    0x34 0xcc             xor $0xcc, %al

  int3               #(7)issue a breakpoint
  jz detected        #(9)jump to detected after breakpoint because zero flag is now set



overall at first glance we would assume that the detected breakpoint would never be reached but with a simple call to push our current address we can manipulate it to jump past some code and change our code on the fly.

this jmping then calling method is also really usefull in finding out where you are in the stack of an buffer overflowed application :3

This post was edited by AbDuCt on Feb 17 2013 03:03am
Member
Posts: 1,358
Joined: Dec 30 2012
Gold: 0.10
Feb 17 2013 03:42am
That's kind of confusing since im an assembly rookie at the moment.

I follow it clearly up to the call enter line.

So here is what I think your code is doing after the enter label is called ( probably wrong )

puts us in the stack
pops the highest 64 bits of the stack into the RCX register
then we increment our RCX address by 1 byte
(why is the "initial push statement" jumped pass?)
then we jump to our RCX address which is the next line in our code(detectbreak) now that we're out of the stack?

After that I'm just completely lost lol. Could you explain and try to provide some clarity?

This post was edited by SelfTaught on Feb 17 2013 03:43am
Member
Posts: 13,425
Joined: Sep 29 2007
Gold: 0.00
Warn: 20%
Feb 17 2013 02:31pm
Quote (SelfTaught @ Feb 17 2013 05:42am)
That's kind of confusing since im an assembly rookie at the moment.

I follow it clearly up to the call enter line.

So here is what I think your code is doing after the enter label is called ( probably wrong )

puts us in the stack
pops the highest 64 bits of the stack into the RCX register
then we increment our RCX address by 1 byte
(why is the "initial push statement" jumped pass?)
then we jump to our RCX address which is the next line in our code(detectbreak) now that we're out of the stack?

After that I'm just completely lost lol. Could you explain and try to provide some clarity?



oh didnt know.

this all has to do with byte codes and memory addresses.

when you issue a "call" command it usually means that you are calling a function so it pushes the next address after the call (aka the push memory address/line) and then jumps to the label your specify. the reason call does this is because it expects a "ret" call at the end of the function that basically does "pop the return address off the stack and jmp to it) but we are miss using the call command to our advantage by never using the "ret" call but instead grabbing the memory address our self and manipulating it and jmping to it.

as for why the push is jummped over ill quickly make a 32bit example and do a objdump on it so i can explain it easier.

(some of the code changed but w/e theory is still here)

when asm is assembled and linked it is saved as byte codes(hex) in the binary, actually all programming languages do this. these byte codes tell the processor to do certain things when they are ran. it is actually possible to create byte code by hand and then compile and link a binary but lets face it asm takes enough time to write as it is lol. (ps thats how exploit shellcode is usually made. i like to make mine from asm then run objdump on it to get they byte code, some people like to write it in C then run objdump on it. its just preference lol)

anyways lets take a look at the memory addresses and byte codes that are used in this program



Code
testasm:     file format elf32-i386


Disassembly of section .text:

08048054 <_start>:
8048054:       eb 05            jmp    804805b <start>      #(1)0xeb is byte code for "short jump"
                                                            #0x05 is how many bytes to jump

08048056 <enter>:
8048056:       59               pop    %ecx                 #(3)call pushed 0x8048060 onto the stack
                                                            #our return address. we put it in ecx
8048057:       41               inc    %ecx                 #we increase our address by 1. (now 0x8048061)
8048058:       ff e1            jmp    *%ecx                #we jump to 0x8048061

0804805a <detected>:
804805a:       cc               int3                        #(5)our final location

0804805b <start>:
804805b:       e8 f6 ff ff ff   call   8048056 <enter>      #(2)0xe8 is "call" and needs a realitive
                                                            #address to offset from its own.
                                                            #0xf6ffffff jmps to enter:

08048060 <detectbreak>:
8048060:       68 6a cc 58 34   push   $0x3458cc6a          #(4)0x68 is push. it starts at 8048060 but
                                                            #since we are jumping to 8048061 we
                                                            #skipped over that push and we are now
                                                            # executing bytecode hidden in the push
# 0x6a 0xcc 0x58 0x34 0xCC                                  
# Translation:
# 0x6a 0xcc             pushb $0xcc                          #0x6a is push byte and 0xcc is the value
# 0x58                  pop %rax                             #0x58 is pop rax (we get 0xcc into rax
# 0x34 0xcc             xor $0xcc, %al                       #0x34 is xor [byte], %al abd 0xcc is the value

8048065:       cc               int3                        #0xcc is "break point"
8048066:       74 f2            je     804805a <detected>   #this line is fucked should be jz but w/e
                                                            #because we set the zero flag in eax this would
                                                            #now jump to the other breakpoint.


hopefully that made some sense. you'll understand it as you continue on your asm adventures.

i also really suggest downloading "programming from the ground up" its a pdf book hosted on some edu site. although it deals with 32bit asm on linux its a great read. i also think at&t linux asm is much easier to learn then windows. i guess its just preference though.

edit:: this jumping technique can also be used for making your code seem like its doing something in a debugger/disasembler but since you are actually executing and jumping around in memory you can be doing something completely different.

This post was edited by AbDuCt on Feb 17 2013 02:39pm
Member
Posts: 1,358
Joined: Dec 30 2012
Gold: 0.10
Feb 18 2013 10:47am
Quote (AbDuCt @ Feb 17 2013 12:31pm)
oh didnt know.

this all has to do with byte codes and memory addresses.

when you issue a  "call" command it usually means that you are calling a function so it pushes the next address after the call (aka the push memory address/line) and then jumps to the label your specify. the reason call does this is because it expects a "ret" call at the end of the function that basically does "pop the return address off the stack and jmp to it) but we are miss using the call command to our advantage by never using the "ret" call but instead grabbing the memory address our self and manipulating it and jmping to it.

as for why the push is jummped over ill quickly make a 32bit example and do a objdump on it so i can explain it easier.

(some of the code changed but w/e theory is still here)

when asm is assembled and linked it is saved as byte codes(hex) in the binary, actually all programming languages do this. these byte codes tell the processor to do certain things when they are ran. it is actually possible to create byte code by hand and then compile and link a binary but lets face it asm takes enough time to write as it is lol. (ps thats how exploit shellcode is usually made. i like to make mine from asm then run objdump on it to get they byte code, some people like to write it in C then run objdump on it. its just preference lol)

anyways lets take a look at the memory addresses and byte codes that are used in this program



Code
testasm:     file format elf32-i386


Disassembly of section .text:

08048054 <_start>:
8048054:       eb 05            jmp    804805b <start>      #(1)0xeb is byte code for "short jump"
                                                            #0x05 is how many bytes to jump

08048056 <enter>:
8048056:       59               pop    %ecx                 #(3)call pushed 0x8048060 onto the stack
                                                            #our return address. we put it in ecx
8048057:       41               inc    %ecx                 #we increase our address by 1. (now 0x8048061)
8048058:       ff e1            jmp    *%ecx                #we jump to 0x8048061

0804805a <detected>:
804805a:       cc               int3                        #(5)our final location

0804805b <start>:
804805b:       e8 f6 ff ff ff   call   8048056 <enter>      #(2)0xe8 is "call" and needs a realitive
                                                            #address to offset from its own.
                                                            #0xf6ffffff jmps to enter:

08048060 <detectbreak>:
8048060:       68 6a cc 58 34   push   $0x3458cc6a          #(4)0x68 is push. it starts at 8048060 but
                                                            #since we are jumping to 8048061 we
                                                            #skipped over that push and we are now
                                                            # executing bytecode hidden in the push
# 0x6a 0xcc 0x58 0x34 0xCC                                  
# Translation:
# 0x6a 0xcc             pushb $0xcc                          #0x6a is push byte and 0xcc is the value
# 0x58                  pop %rax                             #0x58 is pop rax (we get 0xcc into rax
# 0x34 0xcc             xor $0xcc, %al                       #0x34 is xor [byte], %al abd 0xcc is the value

8048065:       cc               int3                        #0xcc is "break point"
8048066:       74 f2            je     804805a <detected>   #this line is fucked should be jz but w/e
                                                            #because we set the zero flag in eax this would
                                                            #now jump to the other breakpoint.


hopefully that made some sense. you'll understand it as you continue on your asm adventures.

i also really suggest downloading "programming from the ground up" its a pdf book hosted on some edu site. although it deals with 32bit asm on linux its a great read. i also think at&t linux asm is much easier to learn then windows. i guess its just preference though.

edit:: this jumping technique can also be used for making your code seem like its doing something in a debugger/disasembler but since you are actually executing and jumping around in memory you can be doing something completely different.


That made more sense.

Alright thanks for the suggestion. Once I start playing around and getting more comfortable with Linux I'll download it and give it a gander.

I bought "Assembly language and Computer Architecture using C++ and Java" just recently and so far it's been a really great book. It's kind of old but it explains everything very well and in depth.

Assembly seems like it's going to be relatively easy to learn, I just can't wait until I can start using it to for the exciting stuff :D



Go Back To Programming & Development Topic List
12Next
Add Reply New Topic New Poll