← Back to DevelopmentAging & Mixing viewer.dll generatorProgramsClan filesInternet Information ServiceOllyDbg tutorialsMiscellaneousSkinsLinks / Files

special_account

← Back to Miscellaneous
If you check the .dat files path in the server executable, you find this table.

OllyDbg - Server side


What's weird is that there's 2 sets of path for these files:
* userinfo (account)
* warehouse
* postbox

The second path is pretty much the same as the first one, except they add 0xA3A3 (in red in the dump) before the file name (except for the warehouse which looks like a nice copy/paste fail).
Those 2 extra characters translate to on a latin NT filesystem.

Let's check where the second paths are used.

#1 .rdata:005E8378..005E8385 : PostBox

OllyDbg - Server side


0044B18A  PUSH OFFSET server_3230_rebuild.005E8378
0044B221  PUSH OFFSET server_3230_rebuild.005E8378
 


OllyDbg - Server side


0044B179  |> \56            PUSH ESI                                 ; /<%s> => [ARG.1]
0044B17A  |.  E8 71FFFFFF   CALL 0044B0F0                            ; |
0044B17F  |.  8B4C24 10     MOV ECX,DWORD PTR SS:[ARG.2]             ; |
0044B183  |.  50            PUSH EAX                                 ; |<%d>
0044B184  |.  A1 585DB608   MOV EAX,DWORD PTR DS:[8B65D58]           ; |ASCII "PostBox"
0044B189  |.  50            PUSH EAX                                 ; |<%s> => [8B65D58] = "PostBox"
0044B18A  |.  68 78835E00   PUSH OFFSET server_3230_rebuild.005E8378 ; |Format = "%s\%d\%s.dat"
0044B18F  |.  51            PUSH ECX                                 ; |Buf => [ARG.2]
0044B190  |.  FF15 0CF35D00 CALL DWORD PTR DS:[<&USER32.wsprintfA>]  ; \USER32.wsprintfA


OllyDbg - Server side


0044B20F  |> \56            PUSH ESI                                 ; /<%s> => [ARG.1]
0044B210  |.  E8 DBFEFFFF   CALL 0044B0F0                            ; |
0044B215  |.  8B0D 585DB608 MOV ECX,DWORD PTR DS:[8B65D58]           ; |ASCII "PostBox"
0044B21B  |.  8B5424 10     MOV EDX,DWORD PTR SS:[ARG.2]             ; |
0044B21F  |.  50            PUSH EAX                                 ; |<%d>
0044B220  |.  51            PUSH ECX                                 ; |<%s> => [8B65D58] = "PostBox"
0044B221  |.  68 78835E00   PUSH OFFSET server_3230_rebuild.005E8378 ; |Format = "%s\%d\%s.dat"
0044B226  |.  52            PUSH EDX                                 ; |Buf => [ARG.2]
0044B227  |.  FF15 0CF35D00 CALL DWORD PTR DS:[<&USER32.wsprintfA>]  ; \USER32.wsprintfA


#2 .rdata:005E8388..005E839C : userinfo & warehouse (fail... because it creates a .dat for a warehouse file, where it should be a .war)

OllyDbg - Server side

0044B31F  PUSH OFFSET server_3230_rebuild.005E8388
0044B72F  PUSH OFFSET server_3230_rebuild.005E8388
 


OllyDbg - Server side

0044B317  |.  8B15 4C5DB608 MOV EDX,DWORD PTR DS:[8B65D4C]           ; ASCII "userinfo"
0044B31D  |.  50            PUSH EAX
0044B31E  |.  52            PUSH EDX
0044B31F  |>  68 88835E00   PUSH OFFSET server_3230_rebuild.005E8388 ; |Format = "DataServer\%s\%d\%s.dat"
0044B324  |.  57            PUSH EDI                                 ; |Buf => ARG.EDI
0044B325  |.  FF15 0CF35D00 CALL DWORD PTR DS:[<&USER32.wsprintfA>]  ; \USER32.wsprintfA


OllyDbg - Server side

0044B727  |.  8B15 505DB608 MOV EDX,DWORD PTR DS:[8B65D50]           ; ASCII "warehouse"
0044B72D  |.  50            PUSH EAX
0044B72E  |.  52            PUSH EDX
0044B72F  |>  68 88835E00   PUSH OFFSET server_3230_rebuild.005E8388 ; |Format = "DataServer\%s\%d\%s.dat"
0044B734  |.  57            PUSH EDI                                 ; |Buf => ARG.EDI
0044B735  |.  FF15 0CF35D00 CALL DWORD PTR DS:[<&USER32.wsprintfA>]  ; \USER32.wsprintfA


#3 .rdata:005E83BC..005E83D7 : userinfo

OllyDbg - Server side

0044B582  PUSH OFFSET server_3230_rebuild.005E83BC


OllyDbg - Server side

0044B575  |.  8B0D 4C5DB608 MOV ECX,DWORD PTR DS:[8B65D4C]           ; ASCII "userinfo"
0044B57B  |.  50            PUSH EAX
0044B57C  |.  51            PUSH ECX
0044B57D  |.  8D5424 50     LEA EDX,[LOCAL.31]
0044B581  |.  52            PUSH EDX
0044B582  |.  68 BC835E00   PUSH OFFSET server_3230_rebuild.005E83BC
0044B587  |>  57            PUSH EDI                                 ; |Buf
0044B588  |.  FF15 0CF35D00 CALL DWORD PTR DS:[<&USER32.wsprintfA>]  ; \USER32.wsprintfA


#4 .rdata:005E843C..005E844C : warehouse

OllyDbg - Server side

0044B8A6  PUSH OFFSET server_3230_rebuild.005E843C


OllyDbg - Server side

0044B89B  |.  A1 505DB608   MOV EAX,DWORD PTR DS:[8B65D50]           ; ASCII "warehouse"
0044B8A0  |.  50            PUSH EAX
0044B8A1  |.  8D4C24 14     LEA ECX,[LOCAL.63]
0044B8A5  |.  51            PUSH ECX
0044B8A6  |>  68 3C845E00   PUSH OFFSET server_3230_rebuild.005E843C ; |Format = "%s\%s\%d\%s.dat"
0044B8AB  |.  53            PUSH EBX                                 ; |Buf
0044B8AC  |.  FFD7          CALL EDI                                 ; \USER32.wsprintfA


As you can see, each second path is referenced twice. Also each primary path is referenced once.
This is because of a test on the account name performed before selecting which path to use.
This test is the same for the 3 file types.
For instance for the warehouse:


OllyDbg - Server side

0044B7B2  |.  8A46 04       MOV AL,BYTE PTR DS:[ESI+4]
0044B7B5  |.  83C4 10       ADD ESP,10
0044B7B8  |.  84C0          TEST AL,AL
0044B7BA  |.  75 65         JNE SHORT 0044B821
0044B7BC  |.  8A46 03       MOV AL,BYTE PTR DS:[ESI+3]
0044B7BF  |.  3C 30         CMP AL,30
0044B7C1  |.  7C 5E         JL SHORT 0044B821
0044B7C3  |.  3C 39         CMP AL,39
0044B7C5  |.  7F 5A         JG SHORT 0044B821
0044B7C7  |.  8A0E          MOV CL,BYTE PTR DS:[ESI]
0044B7C9  |.  80F9 63       CMP CL,63
0044B7CC  |.  74 05         JE SHORT 0044B7D3
0044B7CE  |.  80F9 43       CMP CL,43
0044B7D1  |.  75 16         JNE SHORT 0044B7E9
0044B7D3  |>  8A46 01       MOV AL,BYTE PTR DS:[ESI+1]
0044B7D6  |.  3C 6F         CMP AL,6F
0044B7D8  |.  74 04         JE SHORT 0044B7DE
0044B7DA  |.  3C 4F         CMP AL,4F
0044B7DC  |.  75 0B         JNE SHORT 0044B7E9
0044B7DE  |>  8A46 02       MOV AL,BYTE PTR DS:[ESI+2]
0044B7E1  |.  3C 6D         CMP AL,6D
0044B7E3  |.  74 24         JE SHORT 0044B809
0044B7E5  |.  3C 4D         CMP AL,4D
0044B7E7  |.  74 20         JE SHORT 0044B809
0044B7E9  |>  80F9 6C       CMP CL,6C
0044B7EC  |.  74 05         JE SHORT 0044B7F3
0044B7EE  |.  80F9 4C       CMP CL,4C
0044B7F1  |.  75 2E         JNE SHORT 0044B821
0044B7F3  |>  8A46 01       MOV AL,BYTE PTR DS:[ESI+1]
0044B7F6  |.  3C 70         CMP AL,70
0044B7F8  |.  74 04         JE SHORT 0044B7FE
0044B7FA  |.  3C 50         CMP AL,50
0044B7FC  |.  75 23         JNE SHORT 0044B821
0044B7FE  |>  8A46 02       MOV AL,BYTE PTR DS:[ESI+2]
0044B801  |.  3C 74         CMP AL,74
0044B803  |.  74 04         JE SHORT 0044B809
0044B805  |.  3C 54         CMP AL,54
0044B807  |.  75 18         JNE SHORT 0044B821
(...)                                                                                   ; wsprintf with the primary path
0044B821  |>  8A46 03       MOV AL,BYTE PTR DS:[ESI+3]
0044B824  |.  84C0          TEST AL,AL
0044B826  |.  75 20         JNE SHORT 0044B848
0044B828  |.  8A06          MOV AL,BYTE PTR DS:[ESI]
0044B82A  |.  3C 70         CMP AL,70
0044B82C  |.  74 04         JE SHORT 0044B832
0044B82E  |.  3C 50         CMP AL,50
0044B830  |.  75 16         JNE SHORT 0044B848
0044B832  |>  8A46 01       MOV AL,BYTE PTR DS:[ESI+1]
0044B835  |.  3C 72         CMP AL,72
0044B837  |.  74 04         JE SHORT 0044B83D
0044B839  |.  3C 52         CMP AL,52
0044B83B  |.  75 0B         JNE SHORT 0044B848
0044B83D  |>  8A46 02       MOV AL,BYTE PTR DS:[ESI+2]
0044B840  |.  3C 6E         CMP AL,6E
0044B842  |.  74 50         JE SHORT 0044B894
0044B844  |.  3C 4E         CMP AL,4E
0044B846  |.  74 4C         JE SHORT 0044B894
0044B848  |>  8A06          MOV AL,BYTE PTR DS:[ESI]
0044B84A  |.  3C 63         CMP AL,63
0044B84C  |.  74 04         JE SHORT 0044B852
0044B84E  |.  3C 43         CMP AL,43
0044B850  |.  75 16         JNE SHORT 0044B868
0044B852  |>  8A46 01       MOV AL,BYTE PTR DS:[ESI+1]
0044B855  |.  3C 6F         CMP AL,6F
0044B857  |.  74 04         JE SHORT 0044B85D
0044B859  |.  3C 4F         CMP AL,4F
0044B85B  |.  75 0B         JNE SHORT 0044B868
0044B85D  |>  8A46 02       MOV AL,BYTE PTR DS:[ESI+2]
0044B860  |.  3C 6E         CMP AL,6E
0044B862  |.  74 30         JE SHORT 0044B894
0044B864  |.  3C 4E         CMP AL,4E
0044B866  |.  74 2C         JE SHORT 0044B894


Note: For those who don't know how a text string is stored in the memory, it's actually an array of characters, ending with a 00 (zero zero). You can access each letter knowing its index.
For instance, if my text string is 'development' and I store it in a variable named text, text[0] is 'd', text[1] is 'e', text[2] is 'v', etc.


Translated to human language, it gives this:

Human language


// Length is 4
IF account[4] EQUAL TO 00 THEN

        // 4th: between 0 and 9
        IF account[3] GREATER THAN OR EQUAL TO 0 OR account[3] LESS THAN OR EQUAL TO 9 THEN

                // 1st: 'c' OR 'C'
                IF account[0] EQUAL TO 'c' OR account[0] EQUAL TO 'C' THEN

                        // 2nd: 'o' OR 'O'
                        IF account[1] EQUAL TO 'o' OR account[1] EQUAL TO 'O' THEN

                                // 3rd: 'm' OR 'M'
                                IF account[2] EQUAL TO 'm' OR account[2] EQUAL TO 'M' THEN

                                        // Use secondary path ()
                                        EXIT

                                END IF

                        END IF

                // 1st: 'l' OR 'L'
                ELSE IF account[0] EQUAL TO 'l' OR account[0] EQUAL TO 'L' THEN

                        // 2nd: 'p' OR 'P'
                        IF account[1] EQUAL TO 'p' OR account[1] EQUAL TO 'P' THEN

                                // 3rd: 't' OR 'T'
                                IF account[2] EQUAL TO 't' OR account[2] EQUAL TO 'T' THEN

                                        // Use secondary path ()
                                        EXIT

                                END IF

                        END IF


                END IF

        END IF

END IF

// Length is 3
IF account[3] EQUAL TO 00 THEN

        // 1st: 'p' OR 'P'
        IF account[0] EQUAL TO 'p' OR account[0] EQUAL TO 'P' THEN

                // 2nd: 'r' OR 'R'
                IF account[1] EQUAL TO 'r' OR account[1] EQUAL TO 'R' THEN

                        // 3rd: 'n' OR 'N'
                        IF account[2] EQUAL TO 'n' OR account[2] EQUAL TO 'N' THEN

                                // Use secondary path ()
                                EXIT

                        END IF

                END IF

        END IF

END IF

// 1st: 'c' OR 'C'
IF account[0] EQUAL TO 'c' OR account[0] EQUAL TO 'C' THEN

        // 2nd: 'o' OR 'O'
        IF account[1] EQUAL TO 'o' OR account[1] EQUAL TO 'O' THEN

                // 3rd: 'n' OR 'N'
                IF account[2] EQUAL TO 'n' OR account[2] EQUAL TO 'N' THEN

                        // Use secondary path ()
                        EXIT

                END IF

        END IF

END IF

// Use primary path
EXIT


Basically, we have 4 type of "special accounts" :
- com0 to com9
- lpt0 to lpt9
- prn
- any account starting with 'con'


What are these items doing I have no clue, that's a mystery :D !

Bonus:
If you have a manager written in PHP, and some accounts aren't working, you can use this function to check if you need to use the secondary notation.
It returns true if secondary, false if primary

OllyDbg - Server side

function check_secondary_path($id)
{
        $length = strlen($id);

        // Length < 3
        if($length < 3)
        {
                return false;
        }

        // Length == 4
        if($length == 4)
        {
                $l = ord($string[3]);

                // 4th: between 0 and 9
                if($l >= 0x30 && $l <= 0x39)
                {
                        $l = ord($string[0]);

                        // 1st: == 'c' || == 'C'
                        if($l == 0x63 || $l == 0x43)
                        {
                                $l = ord($string[1]);

                                // 2nd: == 'o' || == 'O'
                                if($l == 0x6F || $l == 0x4F)
                                {
                                        $l = ord($string[2]);

                                        // 3rd: == 'm' || == 'M'
                                        if($l == 0x6D || $l == 0x4D)
                                        {
                                                return true;
                                        }
                                }
                        }

                        // 1st: == 'l' || == 'L'
                        if($l == 0x6C || $l == 0x4C)
                        {
                                $l = ord($string[1]);

                                // 2nd: == 'p' || == 'P'
                                if($l == 0x70 || $l == 0x50)
                                {
                                        $l = ord($string[2]);

                                        // 3rd: == 't' || == 'T'
                                        if($l == 0x74 || $l == 0x54)
                                        {
                                                return true;
                                        }
                                }
                        }
                }
        }

        // Length == 3
        if($length == 3)
        {
                $l = ord($string[0]);

                // 1st: == 'p' || == 'P'
                if($l == 0x70 || $l == 0x50)
                {
                        $l = ord($string[1]);

                        // 2nd: == 'r' || == 'R'
                        if($l == 0x72 || $l == 0x52)
                        {
                                $l = ord($string[2]);

                                // 3rd: == 'n' || == 'N'
                                if($l == 0x6E || $l == 0x4E)
                                {
                                        return true;
                                }
                        }
                }
        }

        $l = ord($string[0]);

        // 1st: == 'c' || == 'C'
        if($l == 0x63 || $l == 0x43)
        {
                $l = ord($string[1]);

                // 2nd: == 'o' || == 'O'
                if($l == 0x6F || $l == 0x4F)
                {
                        $l = ord($string[2]);

                        // 3rd: == 'n' || == 'n'
                        if($l == 0x6E || $l == 0x4E)
                        {
                                return true;
                        }
                }
        }

        return false;
}