flat assembler
Message board for the users of flat assembler.
![]() Goto page 1, 2 Next |
Author |
|
bitRAKE 11 Apr 2009, 01:24
DWORDs are being loaded/stored, but the pointers are only being updated by byte increments - it doesn't make any sense. Why clear EAX only to store ECX into EAX afterward - doesn't make sense. Why clear ECX and then POP ECX? Please, fit those things and repost. Also, you'll need to explain the image format - what are you adding? RGB components, or what?
|
|||
![]() |
|
bitRAKE 11 Apr 2009, 06:49
I think the SHR EDX,30 instruction had me going in the wrong direction; and the goal is to load/store bytes - just to capture a single bit value (ouch). The BT instruction was designed for this.
Reading over your other posts makes it clear that you're translating quite literally - that is where all the XOR REG,REG 's are coming from. Can you post the C code? |
|||
![]() |
|
Madis731 11 Apr 2009, 09:18
Sometimes its easier for me too to see the C code
![]() ![]() |
|||
![]() |
|
pal 11 Apr 2009, 11:31
Hmm good point about the dword and about the counting, I could have kept ecx and just made eax the sub-counter. By the way I am not porting the code directly, I am trying to just do it in ASM without the C code if that makes sense.
This is the full C code (it works but probably isn't that good, and it doesn't return anything I know but meh): Code: #include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]) { AddBitmap("C:\\Users\\Unknown\\in.bmp","C:\\Users\\Unknown\\temp.bmp","C:\\Users\\Unknown\\out.bmp"); } int AddBitmap(char* szOriginal, char* szAdd, char* szOutput) { FILE *pOriginal = fopen(szOriginal,"rb"); if(pOriginal == 0) return 0; FILE *pAdd = fopen(szAdd,"rb"); if(pAdd == 0) goto CleanUp; long lOrigSize, lAddSize; fseek(pOriginal,0,SEEK_END); fseek(pAdd,0,SEEK_END); lOrigSize = ftell(pOriginal); lAddSize = ftell(pAdd); rewind(pOriginal); rewind(pAdd); if((lOrigSize - 0x36)<(8 * (lAddSize - 0x36))) goto CleanUp2; char *szOrigCont = (char*)malloc(lOrigSize); if(szOrigCont == 0) goto CleanUp2; char *szAddCont = (char*)malloc(lAddSize); if(szAddCont == 0) goto CleanUp3; if(fread(szOrigCont,1,lOrigSize,pOriginal)!=lOrigSize) goto CleanUp4; if(fread(szAddCont,1,lAddSize,pAdd)!=lAddSize) goto CleanUp4; FILE *pOutput = fopen(szOutput,"wb"); if(pOutput == 0) goto CleanUp4; char *szOutCont = (char*)malloc(lOrigSize); if(szOutCont == 0) goto CleanUp5; memcpy(szOutCont,szOrigCont,0x36); long i = 0x37, x = 0x37, lShift; for( ; i<=lOrigSize && x<=lAddSize && (lShift=7); x++) while((lShift--)>=0) szOutCont[i] = (szOrigCont[i++] & ~1)|((szAddCont[x] >> lShift) & 1); fwrite(szOutCont,1,lOrigSize,pOutput); free(szOutCont); CleanUp5: fclose(pOutput); CleanUp4: free(szAddCont); CleanUp3: free(szOrigCont); CleanUp2: fclose(pAdd); CleanUp: fclose(pOriginal); return 0; } Quote:
Sorry what do you mean by that? Also when you move a value into a register should it xor automatically (i.e. if I moved al into byte [ebx], all of ebx but bl would remain as it is yeah? So I have to xor before to null the values.). With bt, to get the CF value, should I null al and use setc to get the value? Do I actually need to null it or does CF set it as 0 if the value is 0? |
|||
![]() |
|
bitRAKE 11 Apr 2009, 15:03
A store overwrites whatever was in a register. So, putting a zero in a register prior to overwriting is superfluous. Yet, a partial store might require zeroing the register if the upper bits need to be zero. An example is in order:
Code: xor eax,eax ; not needed mov eax,[edi] ; overwrites full 32-bits of EAX ; partial store example xor eax,eax ; clear all bits mov al,[edi] ; just set low 8-bits of EAX add esi,eax ; use full register EAX ; preferred over partial store movzx eax,byte[edi] add esi,eax If you read the description of SETC it should make clear that either a 00 or 01 is stored - making prior contents of byte history. |
|||
![]() |
|
pal 11 Apr 2009, 16:23
Ahh, thank you I learnt quite a bit from that! Will update if I have anything further done with the code.
When you say bad in terms of performance, do you mean because: Code: xor eax,eax mov al,byte [edi] Takes up one more byte than: Code: movzx eax,byte [edi] Or not? |
|||
![]() |
|
Madis731 11 Apr 2009, 18:04
Its just that movzx does the same as the xor/mov-pair, but with less time. Its a problem with implementation of x86, where writing to a small part of a register will stall the execution of any other instruction that executes on the full register. I think the delay was 1 or 2 clocks.
Its not much, but they can surprise you in critical loops. Btw, we have a Vista user (pal) here ![]() |
|||
![]() |
|
pal 11 Apr 2009, 19:34
Ahh, interesting. Has that problem been fixed with x64 or is it still present? I'll be sure to use movzx from now on, cheers. Was ironic, 10 minutes after bitRAKE told me about that I looked at someones assembly code and corrected them for doing a xor then a partial move
![]() Yeah I run Vista, I'm assuming not many people here do? I'm getting into Linux more and more though, I have it on dual boot, its just me a Linux seriously don't go well together. |
|||
![]() |
|
bitRAKE 12 Apr 2009, 01:15
pal wrote: Has that problem been fixed with x64 or is it still present? Goggling Steganography just now gives me a better idea of the goal. Kind of wondering how much data could be hidden out there in plain sight... |
|||
![]() |
|
pal 12 Apr 2009, 08:44
Yeah I see.
Basically steganography is the art of hiding something within something else. For example you can hide textual information within a BMP header by changing the values of the data offset (it will just be skipped) or in TAR headers (there are 100 bytes of data space to specify the name of an archive; null bytes pad it, so if we find the first null byte, we can start from that +1 and add our data, and again it will be skipped). In this case I'm trying to hide an image in another image as already said. As for the quantity, it depends how you are hiding it. If you are hiding it like I am for example, the maximum I am going to be able to hide is: Size of raw data of original image / 8 (as one bit is added to each byte). For the extraction, we assume that the person knows the size of the image and the number of bits per pixel. On the other hand if we are hiding an image in the TAR files of a Linux distrobution, say there are 1000 files within it. This means there is going to be 1000 * 100 bytes of data for the name, all null padded. So if on average each file name takes up 15 bytes of data, then we have (1000 * 100) - (15 * 1000) = 85,000 bytes of space. We could hide a file which has been compressed in there e.g. a JPG or a PNG, but we couldn't hide a BMP file very easily because they have large file sizes. We could though hide text in this easily, but then we have the problem of it being plaintext etc. Hope that helps? Unless I misunderstood you and you were implying that at me, then my whole text was useless -.- |
|||
![]() |
|
revolution 12 Apr 2009, 09:00
If you are worried about the plaintext aspect then you should encrypt the data before inserting it into the BMP/TAR file.
Also, no need to limit yourself to storing images in the BMP, you can store any arbitrary binary data in the lowest bit. Also, note that there are now some very good algorithms that can detect the presence of hidden data within images. So perhaps they are not hidden as well as you might have imagined. Be careful about what you put there! |
|||
![]() |
|
pal 12 Apr 2009, 10:45
Yeah I know, this is kind of a POC code more than anything, maybe a little utility to hide somethings.
What kind of algorithms are there? I'm assuming they don't just extract possible data, but they recognise encryption algorithms etc? |
|||
![]() |
|
revolution 12 Apr 2009, 11:09
You can consider a normal BMP file as an 8-8-8 data stream. But for a BMP file with "hidden" data the format is 7-7-7 with an extra 1-1-1 data stream.
One simple method is if the 1-1-1 data is some type of unencrypted file then often it is quite obvious it is not part of the image because of particular things, like an .exe file will have a MZ/PE header, or a text file will only have 7-bit data, etc. For this reason some type of scrambling (like encryption) is usually done to avoid this simple detection method and force people to move to more sophisticated methods like the one below. Another, more complex method, is to look at the 7-7-7 portion and compare it to the 1-1-1 portion. With a normal image the patterns match in certain ways, but with a steganographic image the patterns strongly diverge in almost all ways. Hence the detection of something "not normal". And a third method is very simply the fact that you have chosen not to use the more usual compressed format that the average person likes to use. Mr investigator: "So, pal, why did you use a BMP format for your simple holidays shots when everyone else would use JPG? Are you hiding something?" |
|||
![]() |
|
pal 12 Apr 2009, 11:33
:p Cool, thats a good idea about the headers etc. The good thing about storing certain types of file (e.g. BMP) is you don't have to store the header, you can get all the required data from the user (height, width, bits per pixel) and then fill the rest in yourself.
I may have to try to implement that algorithm sometime (the checking one), seems quite interesting. What do you mean by a text file will only have seven bit data though? |
|||
![]() |
|
revolution 12 Apr 2009, 12:00
pal wrote: What do you mean by a text file will only have seven bit data though? |
|||
![]() |
|
pal 12 Apr 2009, 12:13
Ahh yeah, that was a retarded question -.- Cheers.
For using bt, the offset (when I am using a byte for the bitbase), for big endian bit numbering does that start at 7? I.e. We have: 01101001 in ah. Would: bt ah,7 Get the most significat bit or the second most? |
|||
![]() |
|
revolution 12 Apr 2009, 12:22
pal wrote: Would: bt ah,7 Get the most significat bit or the second most? |
|||
![]() |
|
pal 12 Apr 2009, 12:27
Oops, I get the two endians mixed up, need to read up on them more, cheers though, think I nearly have this program done.
By the way, does this site have an IRC channel? |
|||
![]() |
|
bitRAKE 12 Apr 2009, 15:39
The best thing about BT* is that it works with memory addresses and a 32-bit index into the bit array - hurray! So, you want bits 7, 15, 23, 31, 39, ... from the same address. I imagine they would all be cleared in the target (BTR) and then just set the bits that aren't zero in the source (BTS).
[I wonder if any espionage virus tries to send it's data in this fashion? User thinks they are uploading a picture and their personal info gets tacked on for free.] |
|||
![]() |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.