flat assembler
Message board for the users of flat assembler.
Index
> Windows > String functions Goto page Previous 1, 2, 3, 4 Next |
Author |
|
f0dder 06 Feb 2013, 12:59
HaHaAnonymous wrote: I never used libC or use libC (not that I know, if I do, please, let me know). It doesn't matter if you're using an actual libc - as long as you're using "strlen" or "strcpy" (etc), you're using the libc interface. HaHaAnonymous wrote: No, I don't care. Why? --> Because it is impossible to create something that is "un-hackable". By that line of reasoning, you should post your bank account, all personal information, all accounts and passwords. Dunno if it's impossible to write something unhackable, but it certainly is damn hard to do any formal proofs of code correctness once there's any external input. Still, it doesn't mean we shouldn't try to write decent code, and it certainly doesn't mean we should use routines that have known security issues. Especially not when we can get safer and faster by choosing something else. sleepsleep wrote: vid got a complete string function implementation, With a sane & safe interface - still (slow ) zero-terminated strings, though. (No, I didn't say "vid's code is slow", I'm saying "dealing with zero-terminated strings is slower than length-prefixed strings"). |
|||
06 Feb 2013, 12:59 |
|
JohnFound 06 Feb 2013, 13:15
BTW, FreshLib uses some intermediate format for dynamic strings - the string has fields .len on offset -4, but still ends with NULL, in order to be compatible with OS system API in order to not need conversion from and to asciiz. The full definition of the string structure is:
Code: struc string { .capacity dd ? .len dd ? label .data byte } virtual at -(sizeof.string) string string sizeof.string = $-string end virtual The StrPtr procedure returns pointer to .data field of this structure, so the .capacity and .len are negative. You always can do: Code: stdcall StrDup, 'Test string' stdcall StrPtr, eax mov ecx, [esi+string.len] |
|||
06 Feb 2013, 13:15 |
|
revolution 06 Feb 2013, 13:21
I've always liked this slightly better for its nicer looking column alignment:
Code: struc string { .capacity dd ? .len dd ? .data rb 0 } |
|||
06 Feb 2013, 13:21 |
|
JohnFound 06 Feb 2013, 13:30
Yea, it looks better. Although, recently I invented another way to make structures on negative offsets, using "struct" (here is with your trick):
Code: struct string org $-sizeof.string .capacity dd ? .len dd ? .data rb 0 ends |
|||
06 Feb 2013, 13:30 |
|
Kazyaka 06 Feb 2013, 13:38
Picnic,
This isn't good replacement function. I think you've noticed it too. Why? Because we need to allocate a block of memory, before we know a replaced string length. Of course, we can try provide it, but it's easy way to make program crash. So I'm writing my custom function. If you've free time - please check what's wrong. Code: StringRep: mov ebp,esp mov edi,[ebp+4];pSourceString mov esi,[ebp+8];pSearchString xor ecx,ecx ;Equal bytes counter .loop: ;Main loop cmp byte[edi],0 je .loop_end ;If pSourceString end then breaks the loop mov al,[esi+ecx] ;Loads byte pSearchString + counter cmp al,[edi] ;Compares above byte with pSearchString character jne .not_equal .equal: ; Both bytes are equal add ecx,1 add edi,1 mov al,[esi+ecx] cmp al,0 je .loop_end jmp .loop .not_equal: ;Both bytes aren't equal add edi,1 xor ecx,ecx jmp .loop .loop_end: invoke lstrlen, esi ;Return pSearchString length cmp eax,ecx ;If length isn't equal with counter then returns error jne .fail ret .fail: xor eax,eax ret I've added comments. The function should only checks if search string is in main string. There are only two parameters: Code: stdcall StringRep,SourceString,SearchString You can use these strings: Code: SourceString: db "This is string manipulation function!",0 SearchString: db "func",0 |
|||
06 Feb 2013, 13:38 |
|
revolution 06 Feb 2013, 13:50
JohnFound wrote: Yea, it looks better. Although, recently I invented another way to make structures on negative offsets, using "struct" (here is with your trick): |
|||
06 Feb 2013, 13:50 |
|
JohnFound 06 Feb 2013, 14:46
revolution wrote: Oh, but org will break the addressing space into sections. And then you can get 'out of scope' errors. Hm, it seems to work good for me... Maybe I have to make some more tests. Can you provide some example? _________________ Tox ID: 48C0321ADDB2FE5F644BB5E3D58B0D58C35E5BCBC81D7CD333633FEDF1047914A534256478D9 |
|||
06 Feb 2013, 14:46 |
|
Asm++ 06 Feb 2013, 16:00
Kazyaka,
Asm++ wrote: Hi, I have a little question about StringCopy(pSrc, pDest, dwBytes), Kazyaka wrote: You've text "Welcome to the site of flat assembler!", and you want to copy only first word to some other place. Will you copy all bytes? Of course, not. So you must use 7 in this case as the third parameter. Well, then it's better to rename it MemoryCopy or something like that, if you want to copy a defined number of bytes. _________________ Binary is nice, but Assembly is better! |
|||
06 Feb 2013, 16:00 |
|
f0dder 06 Feb 2013, 16:04
Asm++ wrote: Well, then it's better to rename it MemoryCopy or something like that, if you want to copy a defined number of bytes. Very Happy Indeed, that routine is a memcpy. It would be useful, however, specifying the max size of destination - heck, even the size of source - for a string-copy routine, to avoid buffer overflows. Even just reading a buffer can be a security problem |
|||
06 Feb 2013, 16:04 |
|
HaHaAnonymous 06 Feb 2013, 16:05
[ Post removed by author. ]
Last edited by HaHaAnonymous on 28 Feb 2015, 21:41; edited 2 times in total |
|||
06 Feb 2013, 16:05 |
|
f0dder 06 Feb 2013, 16:17
HaHaAnonymous wrote:
See the implementation of StringCopy in the original post _________________ - carpe noctem |
|||
06 Feb 2013, 16:17 |
|
Asm++ 06 Feb 2013, 16:24
HaHaAnonymous wrote:
Nice, so the prototypes would be like: MemoryCopy ( pDes, pSrc, dwBytes) StringCopy ( pDes, pSrc ) Q-Why StringCopy must NOT to have a dwBytes parameter? A-Because it's a STRING function(procedure, routine...), in other words its size is defined by 0(NULL), as it's a Zero Terminated String, so actually StringCopy is just a combination of StringLength(strlen) and MemoryCopy(memcpy). So, if you want to copy a part of a string, then use memcpy, and if you want to copy the whole string, then just use strcpy. _________________ Binary is nice, but Assembly is better! |
|||
06 Feb 2013, 16:24 |
|
HaHaAnonymous 06 Feb 2013, 16:26
[ Post removed by author. ]
Last edited by HaHaAnonymous on 28 Feb 2015, 21:41; edited 1 time in total |
|||
06 Feb 2013, 16:26 |
|
f0dder 06 Feb 2013, 16:27
Asm++: even if you're going to use unsafe interfaces, please don't implement a string copy as string length + memory copy... scan over the source string twice? UGH!
|
|||
06 Feb 2013, 16:27 |
|
Kazyaka 06 Feb 2013, 16:28
Asm++,
Yeah, you're kind of right about this. But if StringCopy is MemoryCopy (saved as RtlMoveMemory in ntdll.dll), you can also say, that StringLen is like a lstrlen or strlen from WinAPI. And it'll the true. So why should you use one of my functions? Just run Cheat Engine or similar tool, and research Microsoft's procedures. They're much larger and slower. It's everything what I can say about this. |
|||
06 Feb 2013, 16:28 |
|
Asm++ 06 Feb 2013, 16:39
f0dder wrote:
Yes, you are right about the buffer overflow and memory read and write violations, but the problem is how to define Save boundaries of the memory where you can manipulate it safely in all cases? setting boundaries MANUALLY by the programmer is NOT an insurance of memory security problems, for example, setting incorrect values and... BOMB, Access Violation, Crash happy software. _________________ Binary is nice, but Assembly is better! |
|||
06 Feb 2013, 16:39 |
|
f0dder 06 Feb 2013, 16:57
Asm++: at compile/assemble time, you know how large your static buffers are - so those can be used directly with sizeof/lengthof (please, no magic numbers scattered all over the source ). For dynamically allocated strings, you should be storing the length of the allocation somewhere.
Your string routines should have buffer-length arguments for both source and target strings, and you should always prefer string-base-address + index-position over pointers pointing to arbitrary positions inside your strings. At least if you want to guard against bugs (and exploits). For nul-terminated strings, these additional checks will in some cases slow down the routines - but outside really sensitive code, IMHO the safety tradeoff is worth it. You also need to pass a few more arguments to your function, but IMHO that's not really a problem either. If at all possible, IMHO one should be using length-prefixed strings (especially people who are worried about the small speed hit of securely dealing with nul-terminated strings). Your string-length becomes a constant-time operation, a string copy is a couple of sanity checks plus a memcopy, et cetera. |
|||
06 Feb 2013, 16:57 |
|
Asm++ 06 Feb 2013, 16:57
f0dder wrote: Asm++: even if you're going to use unsafe interfaces, please don't implement a string copy as string length + memory copy... scan over the source string twice? UGH! I think it's the "Best Solution"(NOT SURE 100%). If I want my code to be small as possible, then I will use movsX(X = b, w, d or q), this instruction NEEDs a COUNTER value in ECX, How to get that value if you will not find the string length first? If I want my code to be as fast as possible, then I will NOT use movsX, but, Is it better to check for 0(NULL), Every time I read a byte value, then decide to copy it or not? Is this an efficient solution? For NOW I Don't think so(I Need to do some speed tests first to be sure). _________________ Binary is nice, but Assembly is better! |
|||
06 Feb 2013, 16:57 |
|
f0dder 06 Feb 2013, 18:24
Well, it depends on your goal - size vs. speed.
But, assuming we follow the windows/x86 register preservation rules and C calling convention, can we do a strcpy-that-relies-on-calling-strlen shorter than this? Code: strcpy:; 24 bytes push esi push edi mov edi, [esp + 12] ; dst mov esi, [esp + 16] ; src push esi call strlen mov ecx, eax rep movsb pop eax ; to get rid of arg for strlen pop edi pop esi ret Here's a couple of straightforward alternatives that don't rely on first calling strlen: Code: strcpy_1: ; 19 bytes push esi push edi mov edi, [esp + 12] ; dst mov esi, [esp + 18] ; src .copy: lodsb stosb test al, al jnz .copy pop edi pop esi ret strcpy_2: ; 19 bytes mov edx, [esp + 4] ; dst mov ecx, [esp + 8] ; src .copy: mov al, [ecx] mov [edx], al inc ecx inc edx test al, al jnz .copy ret Not claiming any of those are optimal (or even good, and they haven't been tested - they're just food for thought. |
|||
06 Feb 2013, 18:24 |
|
Goto page Previous 1, 2, 3, 4 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.