Jump to content
Tuts 4 You

How to handle strings?


Recommended Posts

Hello again,

so I have again a little question for you and hope that you can help.

So the problem is that I am no coder and also don't know all API's and what they can do.So at the moment I need to find some API's of any xy dll which can handle interger and strings quickly.

So what I wanna do is to create a LOG text file in realtime which does log diffrent informations.

1. How to convert integers to a string?


For exsample I have any value 12345678 in eax and want this get back as ASCII string in my buffer.Which API/s can I use for this?

2. How to convert Hex to Dec?


Here I need any API which can convert hex to dec values.AL is 0A hex = 10 dec.Is there any API?

3. Which other APIs do you know which I can use to handle easily strings to create nice and clean outputs later in my LOG text file?


So I see the String Functions in the WinAPI help but I know there are also others from msvcrt.dll [don't know them so just remember this from the past..] etc.So if you know them then just tell me + easy exsample what paramter I have to push [value xy] etc you know [no names pleas like WM_PAINT etc for exsample].

4. Which APIs should I use to create the LOG text file easily?


So here I could use the basic way to use CreateFile / ReadFile / WriteFile / CloseHandle APIs.So the problem is that I need to write the text output peace for peace and not at once so in this case I have always to use the APIs above and need to re-read the text file and need to check the end of the text file where was written the last information.So is there maybe a simple method to prevent this steps etc?

Ok so that all for the moment and hope that you have some infos for me which I can use and test. :) Oh and by the way,so maybe you have already any little targets which does output any text in a file then you can send it to me or if its a basic system tool etc then just tell me the name so that I can debug it to see the way how this files do it etc.

Thank you

Link to comment

Again me so I did forgot a another problem.

So is there a way to use some etc APIs to get the last error reason as string back?So you know Ollys register and there you can see the lastError flag + error reason and now I want to know whether there is a way to get this error string somehow you know.

Lets say I use NTDLL.RtlGetLastWin32Error API then I get the error flag back and with this flag I wanna use any xy API to get the error reason as string back.

O 0  LastErr ERROR_ALREADY_EXISTS (000000B7)-----------------------------7C91FE21 RtlGetLastWin32Error      MOV EAX,DWORD PTR FS:[18]7C91FE27                           MOV EAX,DWORD PTR DS:[EAX+34]7C91FE2A                           RETN-----------------------------push bufferPush eax ; error flagcall API ; any API which I dont know ..buffer = "ERROR_ALREADY_EXISTS" string
So this I mean you know.Of course I have a full list of all errors which is ultra long and I don't want to use ASM compares of each possible error reason to get the right one.So is there any API like this which I can use etc?

Thanks again

Link to comment

1) the function you want is "sprintf(...)". I suggest you do some reading on format strings and check some apps for usage cases.

2) you want to convert strings to numbers? sscnaf scanf(..), atoi(), strtol(),...

3) not sure what else you want from "string apis"

4) none. WriteFile should always set the file pointe to the end of the file, so you can keep doing "WrieFile(...."string",....)". Not sure what yu want to "check".

5) there's probably some way via FormatMessage()

Edited by deepzero
  • Like 1
Link to comment

Hi Deep,

thanks for your answer so far.

00073124   00000000  /CALL to sprintf00073128   00000000  |s = NULL0007312C   00000000  |format = NULLDo you have any little exsamples using this API?I found a long description on the next about this API but don't understand this long text.
What is sscnaf(..), atoi(), strtol(),...?

sscnaf = No API.So you know I am no coder and need some direct stuff / exsample wich I can ASM and execute directly in Olly for testings.Also I mean some how to convert numbers or values in register to a ASCII string.

The rest I will check.


Link to comment

Hi eXoDia,

thanks again. :) Ohhhhh this API works. :)

0022FF3C   0040134A  /CALL to wsprintfA from wsprintf.004013450022FF40   00402000  |s = wsprintf.004020000022FF44   00403024  |Format = "hex: %X, dec: %d"0022FF48   0000000A  |<%X> = A0022FF4C   0000000A  \<%d> = A (10.)"hex: A, dec: 10"
So if I see it right then I just need to use %X and %d right.Coolio.Ok I see there is a bigger description of this API which I need to test more to check what the API can do more.


Link to comment

Check: http://msdn.microsoft.com/en-us/library/windows/desktop/ms647550(v=vs.85).aspx

most used on my side: %X, %u, %d, %s, %c (single character)

also notice this:


so you can do %08X to pad the hex with 0 in the front (10 -> 0000000A)

edit54352: you should use msvcrt!sprintf if you want more features (like floating point printing and bigger buffers)

Edited by Mr. eXoDia
Link to comment

As for point 4. not to read file all the time you can use SetFilePointer. Just open file with CreateFile and before write to file use SetFilePointer to set it to FILE_END.

Link to comment

Thanks again eXoDia so I see this API can do many things and now I need to test this manually in Olly.Is it possible if you could create again a small exe file which used this API with all possible parameters?Just to check this all out in realtime durring tracing to see what happend and to note this what I need. :)

@ ToMKoL

Hmm ok so I will check this API out.So at the moment I think about it whether its a good idea to write a log infos somewhere into a memory block so on this way I could use the CreateFile API with the paramter Create_Always to create the log file without to re-read the log file again + finding the end where was something written etc you know.

Exsample: I stop on address xy and want to log the register for exsample.Now I create this text in memory and count the lenght and create the log file with this text.Now on a next stop at other address xy I want to log again the register and add this new infos again in the memory block [now there are 2 register infos] and let create a new LOG file so that the created LOG before will overwritten again and again and again on each new stop etc.So is this a good way or not?So I think not or?


Link to comment

wsprintf will work just fine for your purposes. msvcrt will not always be available (it's part of the c/cpp runtime, not windows).


this will append the string to an existing file, the file has to exists already.

void AppendToFile()
    HANDLE hf = CreateFileA("c:\\log.txt", GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
    SetFilePointer(hf, 0, 0, FILE_END);
    DWORD wrtn;
    WriteFile(hf, "some log string", 15, &wrtn, 0);

/> \55                       PUSH EBP
|.  8BEC                     MOV EBP,ESP
|.  81EC D8000000            SUB ESP,0D8
|.  53                       PUSH EBX
|.  56                       PUSH ESI
|.  57                       PUSH EDI                                            ;  ntdll.7C910228
|.  8DBD 28FFFFFF            LEA EDI,[LOCAL.54]
|.  B9 36000000              MOV ECX,36
|.  F3:AB                    REP STOS DWORD PTR ES:[EDI]
|.  8BF4                     MOV ESI,ESP
|.  6A 00                    PUSH 0                                              ; /hTemplateFile = NULL
|.  6A 00                    PUSH 0                                              ; |Attributes = 0
|.  6A 03                    PUSH 3                                              ; |Mode = OPEN_EXISTING
|.  6A 00                    PUSH 0                                              ; |pSecurity = NULL
|.  6A 00                    PUSH 0                                              ; |ShareMode = 0
|.  68 000000C0              PUSH C0000000                                       ; |Access = GENERIC_READ|GENERIC_WRITE
|.  68 50574100              PUSH 00415750                                       ; |FileName = "c:\\log.txt"
|.  FF15 B8814100            CALL DWORD PTR DS:[<&KERNEL32.CreateFileA>]         ; \CreateFileA
|.  3BF4                     CMP ESI,ESP
|.  E8 3EFDFFFF              CALL 0041114F
|.  8945 F8                  MOV [LOCAL.2],EAX
|.  8BF4                     MOV ESI,ESP
|.  6A 02                    PUSH 2                                              ; /Origin = FILE_END
|.  6A 00                    PUSH 0                                              ; |pOffsetHi = NULL
|.  6A 00                    PUSH 0                                              ; |OffsetLo = 0
|.  8B45 F8                  MOV EAX,[LOCAL.2]                                   ; |kernel32.7C817778
|.  50                       PUSH EAX                                            ; |hFile = NULL
|.  FF15 B4814100            CALL DWORD PTR DS:[<&KERNEL32.SetFilePointer>]      ; \SetFilePointer
|.  3BF4                     CMP ESI,ESP
|.  E8 22FDFFFF              CALL 0041114F
|.  8BF4                     MOV ESI,ESP
|.  6A 00                    PUSH 0                                              ; /pOverlapped = NULL
|.  8D45 EC                  LEA EAX,[LOCAL.5]                                   ; |
|.  50                       PUSH EAX                                            ; |pBytesWritten = NULL
|.  6A 0F                    PUSH 0F                                             ; |nBytesToWrite = F (15.)
|.  68 3C574100              PUSH 0041573C                                       ; |Buffer = lcfsnipp.0041573C
|.  8B4D F8                  MOV ECX,[LOCAL.2]                                   ; |kernel32.7C817778
|.  51                       PUSH ECX                                            ; |hFile = 0012FFB0
|.  FF15 B0814100            CALL DWORD PTR DS:[<&KERNEL32.WriteFile>]           ; \WriteFile
|.  3BF4                     CMP ESI,ESP
|.  E8 02FDFFFF              CALL 0041114F
|.  8BF4                     MOV ESI,ESP
|.  8B45 F8                  MOV EAX,[LOCAL.2]                                   ;  kernel32.7C817778
|.  50                       PUSH EAX                                            ; /hObject = NULL
|.  FF15 AC814100            CALL DWORD PTR DS:[<&KERNEL32.CloseHandle>]         ; \CloseHandle
|.  3BF4                     CMP ESI,ESP
|.  E8 EFFCFFFF              CALL 0041114F
|.  52                       PUSH EDX                                            ;  ntdll.KiFastSystemCallRet
|.  8BCD                     MOV ECX,EBP
|.  50                       PUSH EAX
|.  8D15 88144100            LEA EDX,DWORD PTR DS:[411488]
|.  E8 22FCFFFF              CALL 00411091
|.  58                       POP EAX                                             ;  kernel32.7C81776F
|.  5A                       POP EDX                                             ;  kernel32.7C81776F
|.  5F                       POP EDI                                             ;  kernel32.7C81776F
|.  5E                       POP ESI                                             ;  kernel32.7C81776F
|.  5B                       POP EBX                                             ;  kernel32.7C81776F
|.  81C4 D8000000            ADD ESP,0D8
|.  3BEC                     CMP EBP,ESP
|.  E8 CEFCFFFF              CALL 0041114F
|.  8BE5                     MOV ESP,EBP
|.  5D                       POP EBP                                             ;  kernel32.7C81776F
\.  C3                       RETN

Link to comment
msvcrt will not always be available (it's part of the c/cpp runtime, not windows).



Msvcrt.dll is available on Windows

I use Msvcrt in my Asm projects

Edited by ragdog
Link to comment


hhmmm so something is wrong Deep...

<0100739D>@LOG:"LOG.txt\0"@SRTING:"some log string\0"@FREE:"\x00\x00\x00\x00"@top:	PUSH 0	push 0        push OPEN_EXISTING        push 0	push 0	push C0000000	push @LOG	call CreateFileA	mov edi, eax ; handle	push 2	push 0	push 0	push edi	call SetFilePointer	mov esi, eax ; wrtn	mov [@FREE], esi			push 0	push @FREE ; wrtn	push F     ; lenght	push @SRTING	push edi	call WriteFile		push edi	call CloseHandle
So it writes not the text into the file so it only writes some strange sings into that file!?!Whats wrong now?


Link to comment

So the problem is the SetFilePointer API so if I use it before using WriteFile API then in the text file will only written some four corners signs. :) .....ok wait so now it seems to work,so I think there was a problem with the file which I open before closing the handle + keep it open or something.Ok I will check this API out now with some text peaces.Thanks again.


Link to comment


how can I convert any value like in eax 00ABCDEF to a ASCII string "00ABCDEF"?Sorry I am getting totaly confuse with this API descriptions so I need some exsamples [Olly or MultiASM style etc].

So what I need are only some basic stuff that all.

- Hex numbers to ASCII string ABC to "ABC" and or "00000ABC" too

- ASCII string 0-F to numbers like "4a896" to 4A896

- etc

push bufferpush eax ; some value 00ABCDEFcall API xy ; = ASCII string in buffer "00ABCDEF"push buffer ; 404000push eax ; Pointer to ASCII string 403000 | 30 30 41 42 43 44 45 46 | 00ABCDEFcall API xy ; = Hex string in buffer ; 404000 | 00ABCDEF | EF CD AB 00 | ïÍ«.
Just post any exsample so this would be nice to get it working like I did post above as exsamples so I think I will just need this for the moment.

Thanks again

Link to comment

To print EAX to a buffer just use wsprintf with %X. It always print a string, you're just telling it to print as a hex value. Using %d will print the same number but in base 10 (still printed as a string though)


If you need to specify that you want leading zeros then you set the length e.g. %08X


For the other way round I generally use strtoul in C or use my own loop reading byte by byte in MASM

Link to comment

Hi Loki,

thanks again.Ah ok again this API.

0022FF3C   00401000  /CALL to wsprintfA0022FF40   00402000  |s = wsprintf.004020000022FF44   00403000  |Format = "%X"0022FF48   12345678  \<%X> = 12345678Return00402000  31 32 33 34 35 36 37 38  12345678
Ok now it works so to get a string back.Damit,so yesterday I wrote already a bunch of code which can do this and now I just need to use this API on that way. :)

Ok its more clear now a little and what can I do to get the ASCII string as number?Lets say I have for exsample this ASCII string from above at 00402000 so how can I change this now to a value which I can copy in any register?

00402000  31 32 33 34 35 36 37 38  12345678 <-- ASCIIpush paramter xycall API xyReturn = 12345678 in eax or in buffer...ADDR     | Value      | ASCII-------------------------------00402000  12345678     xV4-------------------------------
Yes I found also some infos about this API strtoul but I don't have a clue how to use this correctly [parameters I mean].


Link to comment

using Lokis api:

void strtols()
    long a = strtoul("0xABCD", 0, 16);
    long b = strtoul("1234", 0, 10);

004114E0 main                6A 10                          PUSH 10                                             ; 16 = hex
004114E2                     6A 00                          PUSH 0
004114E4                     68 C8574100                    PUSH 004157C8                                       ; ASCII "0xABCD"
004114E9                     FF15 E8824100                  CALL DWORD PTR DS:[<&msvcrt.strtoul>]             ; MSVCR90D.strtoul
004114EF                     83C4 0C                        ADD ESP,0C
004114F2                     3BF4                           CMP ESI,ESP
004114F4                     E8 60FCFFFF                    CALL 00411159
004114F9                     8945 F8                        MOV DWORD PTR SS:[EBP-8],EAX
004114FC                     8BF4                           MOV ESI,ESP
004114FE                     6A 0A                          PUSH 0A                                             ; 10 -> dec
00411500                     6A 00                          PUSH 0
00411502                     68 60574100                    PUSH 00415760                                       ; ASCII "1234"
00411507                     FF15 E8824100                  CALL DWORD PTR DS:[<&msvcrt.strtoul>]             ; MSVCR90D.strtoul

result is returned in eax.


you might have to load msvcrt.dll yourself, if the target doesnt use it.

Edited by deepzero
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Create New...