How should stack strings be initialized in C shellcode? - c

I'm trying to optimize my shellcode project by introducing a method to store strings as unit64_t values in an array. The shellcode project is written without any optimizations (Debug only) as I want to control everything at the opcode level i.e., the shellcode has precomputed offsets to local variables. If /O2 optimizations were enabled, it might rearrange the C shellcode and mess things up?
For example, currently the shellcode has these stack arrays defined
char calc[] = { 'c','a','l','c','.','e','x','e',0 };
char winexec[] = { 'W','i','n','E','x','e','c',0 };
char sleep[] = { 'S','l','e','e','p',0 };
char createtoolhelp32snapshot[] = { 'C','r','e','a','t','e','T','o','o','l','h','e','l','p','3','2','S','n','a','p','s','h','o','t',0 };
char process32first[] = { 'P','r','o','c','e','s','s','3','2','F','i','r','s','t',0 };
char process32next[] = { 'P','r','o','c','e','s','s','3','2','N','e','x','t',0 };
char closehandle[] = { 'C','l','o','s','e','H','a','n','d','l','e',0 };
char openprocess[] = { 'O','p','e','n','P','r','o','c','e','s','s',0 };
char virtualallocex[] = { 'V','i','r','t','u','a','l','A','l','l','o','c','E','x',0 };
char virtualfreeex[] = { 'V','i','r','t','u','a','l','F','r','e','e','E','x',0 };
char writeprocessmemory[] = { 'W','r','i','t','e','P','r','o','c','e','s','s','M','e','m','o','r','y',0 };
char createremotethread[] = { 'C','r','e','a','t','e','R','e','m','o','t','e','T','h','r','e','a','d',0 };
char comparestringa[] = { 'C','o','m','p','a','r','e','S','t','r','i','n','g','A',0};
char notepad[] = { 'n','o','t','e','p','a','d','.','e','x','e',0 };
char getcurrentprocessid[] = { 'G','e','t','C','u','r','r','e','n','t','P','r','o','c','e','s','s','I','d',0 };
char exitthread[] = { 'E','x','i','t','T','h','r','e','a','d',0 };
The generated assembly is
52: char calc[] = { 'c','a','l','c','.','e','x','e',0 };
00007FF6248B1C6D C6 45 08 63 mov byte ptr [calc],63h
00007FF6248B1C71 C6 45 09 61 mov byte ptr [rbp+9],61h
00007FF6248B1C75 C6 45 0A 6C mov byte ptr [rbp+0Ah],6Ch
00007FF6248B1C79 C6 45 0B 63 mov byte ptr [rbp+0Bh],63h
00007FF6248B1C7D C6 45 0C 2E mov byte ptr [rbp+0Ch],2Eh
00007FF6248B1C81 C6 45 0D 65 mov byte ptr [rbp+0Dh],65h
00007FF6248B1C85 C6 45 0E 78 mov byte ptr [rbp+0Eh],78h
00007FF6248B1C89 C6 45 0F 65 mov byte ptr [rbp+0Fh],65h
00007FF6248B1C8D C6 45 10 00 mov byte ptr [rbp+10h],0
53: char winexec[] = { 'W','i','n','E','x','e','c',0 };
00007FF6248B1C91 C6 45 38 57 mov byte ptr [winexec],57h
00007FF6248B1C95 C6 45 39 69 mov byte ptr [rbp+39h],69h
00007FF6248B1C99 C6 45 3A 6E mov byte ptr [rbp+3Ah],6Eh
00007FF6248B1C9D C6 45 3B 45 mov byte ptr [rbp+3Bh],45h
00007FF6248B1CA1 C6 45 3C 78 mov byte ptr [rbp+3Ch],78h
00007FF6248B1CA5 C6 45 3D 65 mov byte ptr [rbp+3Dh],65h
00007FF6248B1CA9 C6 45 3E 63 mov byte ptr [rbp+3Eh],63h
00007FF6248B1CAD C6 45 3F 00 mov byte ptr [rbp+3Fh],0
To improve performance, should those arrays be replaced with
uint64_t calc[] = { 0x6578652e636c6163, 0x0000000000000000 };
uint64_t winexec[] = { 0x00636578456e6957 };
uint64_t sleep[] = { 0x0000007065656c53 };
uint64_t createtoolhelp32snapshot[] = { 0x6f54657461657243, 0x3233706c65686c6f, 0x746f687370616e53, 0x0000000000000000 };
uint64_t process32first[] = { 0x33737365636f7250, 0x0000747372694632 };
uint64_t process32next[] = { 0x33737365636f7250, 0x0000007478654e32 };
uint64_t closehandle[] = { 0x6e614865736f6c43, 0x0000000000656c64 };
uint64_t openprocess[] = { 0x636f72506e65704f, 0x0000000000737365 };
uint64_t virtualallocex[] = { 0x416c617574726956, 0x00007845636f6c6c };
uint64_t virtualfreeex[] = { 0x466c617574726956, 0x0000007845656572 };
uint64_t writeprocessmemory[] = { 0x6f72506574697257, 0x6f6d654d73736563, 0x0000000000007972 };
uint64_t createremotethread[] = { 0x6552657461657243, 0x6572685465746f6d, 0x0000000000006461 };
uint64_t comparestringa[] = { 0x53657261706d6f43, 0x000041676e697274 };
uint64_t notepad[] = { 0x2e64617065746f6e, 0x0000000000657865 };
uint64_t getcurrentprocessid[] = { 0x6572727543746547, 0x7365636f7250746e, 0x0000000000644973 };
uint64_t exitthread[] = { 0x6572685474697845, 0x0000000000006461 };
The generated assembly is
71: unsigned long long calc[] = { 0x6578652e636c6163, 0x0000000000000000 };
00007FF7EF7C1C5C 48 B8 63 61 6C 63 2E 65 78 65 mov rax,6578652E636C6163h
00007FF7EF7C1C66 48 89 45 08 mov qword ptr [calc],rax
00007FF7EF7C1C6A 48 C7 45 10 00 00 00 00 mov qword ptr [rbp+10h],0
72: unsigned long long winexec[] = {0x00636578456e6957};
00007FF7EF7C1C72 48 B8 57 69 6E 45 78 65 63 00 mov rax,636578456E6957h
00007FF7EF7C1C7C 48 89 45 38 mov qword ptr [winexec],rax
Question
The shellcode works correctly with both definitions but is the extra performance worth degrading the readability?
Tool
https://godbolt.org/z/eYhWPG9E6

Related

Pixel conversion in decompiled assembly from Ghidra

I'm reversing an assembly function that I believe is converting an array of pixels (RGB) or photosites (RGGB) into a final array with an original (I think) encoding made of 10bits or 12bits per pixel. My goal is to understand in terms of c/c++ operations or natural language in the context of image format conversion what is happening, and in the end name in a meaningful way the variables.
There are few operation that I do not understand such as:
In the case of 10 bits per sample (1 sample ie., R|G|B):
uVar7 = (int64)iVar3 / 3 + ((int64)iVar3 >> 0x3f) & 0xffffffff; // 3f = 63
int iVar4 = (int)uVar7 + (int)(uVar7 >> 0x1f); // 1f = 31
puVar1 = (uint*)((int64)outData + (int64)iVar4 * 4);
*puVar1 = *puVar1 | (*inPixel & 0x3ff) <<
(((char)iVar3 + (char)iVar4 * -3) * '\n' + 2U & 0x1f);
The first two lines are considering the strongest bit (>> 0x3f and >> 0x1f); but why divide by 3 ?
why add the strongest bit ? I don't get the 4th line at all; * -3 * '\n' in particular, and 2U & 0x1f: why 31 as mask ?
and in the case of 12 bits per samples:
uint uVar8 = *inPixel & 0xfff; // considering an array of 3 bits (likely 4 times at some point)
uint uVar5 = surfaceSizeBits + position_ >> 0x1f & 7; // 7 = b111
& 7 is zeroing all but the 3 lowests bits, but why after considering the strongest bit just before ?
dataSizeBytes_ = surfaceSizeBits + position_ + uVar5;
iVar3 = ((dataSizeBytes_ & 7) - uVar5) * 12;
I don't get the purpose of - uVar5 and then *12; it's possible that dataSizeBytes is not data size in bytes here.
uint uVar6 = iVar3 >> 0x1f & 0x1f;
uVar5 = iVar3 + uVar6;
iVar3 = (uVar5 & 0x1f) - uVar6;
puVar1 = (uint*)((int64)outData +
((int64)((int)dataSizeBytes_ >> 3) * 3 +
(int64)((int)uVar5 >> 5)) * 4);
>>3 is "dropping the 2 weakest bits" but that's all I understand here.
byte bVar2 = (byte)iVar3;
*puVar1 = *puVar1 | uVar8 << (bVar2 & 0x1f);
if (0x14 < iVar3) // 0x14 = 20
puVar1[1] = puVar1[1] | uVar8 >> (0x20 - bVar2 & 0x1f); //0x20 = 32
Here I understand the bit operations but I can't move to a higher level.
End of 12 bits case.
For the decompiled code, I provided those definitions in order to help understanding:
typedef unsigned int uint;
typedef unsigned long long uint64;
typedef long long int64;
typedef int undefined; //may be wrong, may be 1 byte (int4) instead
typedef long int32;
typedef long undefined8;
typedef int int16;
typedef int int16;
typedef short int8;
typedef unsigned short uint8;
typedef unsigned short ushort;
typedef long code;
char LogBuffer[256];
The undefined* are from ghidra, I did not check yet in dynamic analysis if my translation is correct.
The decompiled code from ghidra is:
(modulo few renamings and type definitions)
undefined8
PixelConversionInOut
(undefined8 param_1, void* inData, void* outData, int height, int widthStride,
int bitsPerSample, int dstBufferSize, uint* bufferResult)
{
uint* puVar1;
int surfaceSizeBits;
undefined8 status;
int iVar3;
uint64 uVar7;
int64 currentPosition;
uint dataSizeBytes_;
GetCurrentThreadId();
if (inData != (void*)nullptr && outData != (void*)nullptr)
{
int heightPadding = 0;
*bufferResult = 0;
if (bitsPerSample == 10)
{
if ((height == 0x818) || (height == 0x1010))
heightPadding = 4;
else if (height == 0x1018)
heightPadding = 2;
}
int heightPadded = heightPadding + height;
if (bitsPerSample == 10)
{
currentPosition = (int64)(heightPadded * widthStride * 4);
uVar7 = currentPosition / 3 + (currentPosition >> 0x3f) & 0xffffffff;
*bufferResult = (int)uVar7 + (int)(uVar7 >> 0x1f);
}
else
{
if (bitsPerSample == 0xc)
{
surfaceSizeBits = heightPadded * widthStride * 0xc;
dataSizeBytes_ = (int)(surfaceSizeBits + (surfaceSizeBits >> 0x1f & 7U)) >> 3;
}
else
dataSizeBytes_ = heightPadded * widthStride * 4 / 2;
*bufferResult = dataSizeBytes_;
}
dataSizeBytes_ = *bufferResult;
if (dstBufferSize < (int)dataSizeBytes_)
{
sprintf(LogBuffer, "dstBuffer must be allocated at least %d bytes.", (uint64)dataSizeBytes_);
status = 0x80000003;
}
else
{
if (bitsPerSample == 0x10)
{
memcpy(outData, inData, (int64)(int)dataSizeBytes_);
GetCurrentThreadId();
status = 0;
}
else
{
memset(outData, 0, (int64)(int)dataSizeBytes_);
currentPosition = 0;
if (0 < widthStride)
{
surfaceSizeBits = 0;
do
{
int position_ = 0;
if (0 < (int64)(heightPadded - heightPadding))
{
ushort* inPixel = (ushort*)((int64)inData + height * currentPosition * 2);
int64 rowsRemaining = (int64)(heightPadded - heightPadding);
do
{
if (bitsPerSample == 10)
{
iVar3 = surfaceSizeBits + position_;
uVar7 = (int64)iVar3 / 3 + ((int64)iVar3 >> 0x3f) & 0xffffffff;
int iVar4 = (int)uVar7 + (int)(uVar7 >> 0x1f);
puVar1 = (uint*)((int64)outData + (int64)iVar4 * 4);
*puVar1 = *puVar1 | (*inPixel & 0x3ff) <<
(((char)iVar3 + (char)iVar4 * -3) * '\n' + 2U & 0x1f);
}
else
{
if (bitsPerSample == 12)
{
uint uVar8 = *inPixel & 0xfff;
uint uVar5 = surfaceSizeBits + position_ >> 0x1f & 7;
dataSizeBytes_ = surfaceSizeBits + position_ + uVar5;
iVar3 = ((dataSizeBytes_ & 7) - uVar5) * 12;
uint uVar6 = iVar3 >> 0x1f & 0x1f;
uVar5 = iVar3 + uVar6;
iVar3 = (uVar5 & 0x1f) - uVar6;
puVar1 = (uint*)((int64)outData +
((int64)((int)dataSizeBytes_ >> 3) * 3 +
(int64)((int)uVar5 >> 5)) * 4);
byte bVar2 = (byte)iVar3;
*puVar1 = *puVar1 | uVar8 << (bVar2 & 0x1f);
if (0x14 < iVar3)
puVar1[1] = puVar1[1] | uVar8 >> (0x20 - bVar2 & 0x1f);
}
}
position_ = position_ + 1;
inPixel = inPixel + 1;
rowsRemaining = rowsRemaining + -1;
}
while (rowsRemaining != 0);
}
currentPosition = currentPosition + 1;
surfaceSizeBits = surfaceSizeBits + heightPadded;
}
while (currentPosition < widthStride);
}
GetCurrentThreadId();
status = 0;
}
}
return status;
}
return 0x80000023;
}
Here is the original assembly but ghidra did not complain or warn about the result.
**************************************************************
* FUNCTION *
**************************************************************
undefined8 __fastcall PixelConversionInOut(undefined8 pa
undefined8 RAX:8 <RETURN> XREF[1]: 180037b9c(W)
undefined8 RCX:8 param_1
void * RDX:8 inData
void * R8:8 outData
int R9D:4 height
int Stack[0x28]:4 widthStride XREF[1]: 180037b66(R)
int Stack[0x30]:4 bitsPerSample XREF[1]: 180037b26(R)
int Stack[0x38]:4 dstBufferSize XREF[1]: 180037bb8(R)
uint * Stack[0x40]:8 bufferResult XREF[1]: 180037b19(R)
undefined4 EDI:4 heightPadding XREF[2]: 180037b62(W),
180037d1e(W)
undefined4 EAX:4 surfaceSizeBits XREF[2]: 180037b9c(W),
180037bd7(W)
undefined8 RAX:8 status XREF[1]: 180037bd7(W)
undefined8 R10:8 inPixel XREF[1]: 180037c71(W)
undefined4 R11D:4 position_ XREF[1]: 180037d17(W)
undefined8 RDI:8 rowsRemaining XREF[1]: 180037d1e(W)
undefined8 RBP:8 currentPosition XREF[1]: 180037d2c(W)
undefined4 Stack[0x20]:4 local_res20 XREF[2]: 180037ae0(W),
180037c5c(R)
undefined8 Stack[0x18]:8 local_res18 XREF[2]: 180037b21(W),
180037be1(R)
undefined8 Stack[0x10]:8 local_res10 XREF[2]: 180037ae5(W),
180037c61(R)
undefined8 Stack[0x8]:8 local_res8 XREF[4]: 180037aea(W),
180037c23(W),
180037c40(R),
180037d27(R)
undefined8 Stack[-0x20]:8 local_20 XREF[2]: 180037c14(W),
180037d40(R)
undefined8 Stack[-0x28]:8 local_28 XREF[2]: 180037b2d(W),
180037bdc(R)
undefined8 Stack[-0x30]:8 local_30 XREF[2]: 180037b34(W),
180037be6(R)
undefined8 Stack[-0x38]:8 local_38 XREF[2]: 180037c33(W),
180037d3b(R)
undefined4 HASH:27f0811 heightPadded
undefined4 HASH:5fcc647 dataSizeBytes_
PixelConversionInOut XREF[2]: GetDecompressedData:1800384fa(c),
FUN_180038630:18003875a(c)
180037ae0 44 89 4c 24 20 MOV dword ptr [RSP + local_res20],height
180037ae5 48 89 54 24 10 MOV qword ptr [RSP + local_res10],inData
180037aea 48 89 4c 24 08 MOV qword ptr [RSP + local_res8],param_1
180037aef 56 PUSH RSI
180037af0 41 56 PUSH R14
180037af2 41 57 PUSH R15
180037af4 48 83 ec 40 SUB RSP,0x40
180037af8 41 8b f1 MOV ESI,height
180037afb 4d 8b f8 MOV R15,outData
180037afe 4c 8b f2 MOV R14,inData
180037b01 ff 15 29 7d CALL qword ptr [->KERNEL32.DLL::GetCurrentThreadId]
9d 00
180037b07 4d 85 f6 TEST R14,R14
180037b0a 0f 84 42 02 JZ LAB_180037d52
00 00
180037b10 4d 85 ff TEST R15,R15
180037b13 0f 84 39 02 JZ LAB_180037d52
00 00
180037b19 4c 8b 94 24 MOV R10,qword ptr [RSP + bufferResult]
98 00 00 00
180037b21 48 89 5c 24 70 MOV qword ptr [RSP + local_res18],RBX
180037b26 8b 9c 24 88 MOV EBX,dword ptr [RSP + bitsPerSample]
00 00 00
180037b2d 48 89 7c 24 30 MOV qword ptr [RSP + local_28],RDI
180037b32 33 ff XOR EDI,EDI
180037b34 4c 89 64 24 28 MOV qword ptr [RSP + local_30],R12
180037b39 41 89 3a MOV dword ptr [R10],EDI
180037b3c 83 fb 0a CMP EBX,0xa
180037b3f 75 21 JNZ LAB_180037b62
180037b41 8b ce MOV param_1,ESI
180037b43 81 e9 18 08 SUB param_1,0x818
00 00
180037b49 74 12 JZ LAB_180037b5d
180037b4b 81 e9 f8 07 SUB param_1,0x7f8
00 00
180037b51 74 0a JZ LAB_180037b5d
180037b53 83 f9 08 CMP param_1,0x8
180037b56 75 0a JNZ LAB_180037b62
180037b58 8d 7b f8 LEA EDI,[RBX + -0x8]
180037b5b eb 05 JMP LAB_180037b62
LAB_180037b5d XREF[2]: 180037b49(j), 180037b51(j)
180037b5d bf 04 00 00 00 MOV EDI,0x4
LAB_180037b62 XREF[3]: 180037b3f(j), 180037b56(j),
180037b5b(j)
180037b62 44 8d 24 37 LEA R12D,[heightPadding + RSI*0x1]
180037b66 8b b4 24 80 MOV ESI,dword ptr [RSP + widthStride]
00 00 00
180037b6d 83 fb 0a CMP EBX,0xa
180037b70 75 1c JNZ LAB_180037b8e
180037b72 41 8b cc MOV param_1,R12D
180037b75 b8 56 55 55 55 MOV EAX,0x55555556
180037b7a 0f af ce IMUL param_1,ESI
180037b7d c1 e1 02 SHL param_1,0x2
180037b80 f7 e9 IMUL param_1
180037b82 8b c2 MOV EAX,inData
180037b84 c1 e8 1f SHR EAX,0x1f
180037b87 03 d0 ADD inData,EAX
180037b89 41 89 12 MOV dword ptr [R10],inData
180037b8c eb 27 JMP LAB_180037bb5
LAB_180037b8e XREF[1]: 180037b70(j)
180037b8e 41 8b c4 MOV EAX,R12D
180037b91 0f af c6 IMUL EAX,ESI
180037b94 83 fb 0c CMP EBX,0xc
180037b97 75 11 JNZ LAB_180037baa
180037b99 8d 04 40 LEA EAX,[RAX + RAX*0x2]
180037b9c c1 e0 02 SHL surfaceSizeBits,0x2
180037b9f 99 CDQ
180037ba0 83 e2 07 AND inData,0x7
180037ba3 03 c2 ADD surfaceSizeBits,inData
180037ba5 c1 f8 03 SAR surfaceSizeBits,0x3
180037ba8 eb 08 JMP LAB_180037bb2
LAB_180037baa XREF[1]: 180037b97(j)
180037baa c1 e0 02 SHL surfaceSizeBits,0x2
180037bad 99 CDQ
180037bae 2b c2 SUB surfaceSizeBits,inData
180037bb0 d1 f8 SAR surfaceSizeBits,1
LAB_180037bb2 XREF[1]: 180037ba8(j)
180037bb2 41 89 02 MOV dword ptr [R10],surfaceSizeBits
LAB_180037bb5 XREF[1]: 180037b8c(j)
180037bb5 49 63 02 MOVSXD surfaceSizeBits,dword ptr [R10]
180037bb8 3b 84 24 90 CMP surfaceSizeBits,dword ptr [RSP + dstBufferSize]
00 00 00
180037bbf 7e 34 JLE LAB_180037bf5
180037bc1 48 8d 15 30 LEA inData,[s_dstBuffer_must_be_allocated_at_l_180b675f8] = "dstBuffer must be allocated at least %d bytes."
fa b2 00
180037bc8 48 8d 0d 81 LEA param_1,[LogBuffer] = ??
db bc 00
180037bcf 44 8b c0 MOV outData,surfaceSizeBits
180037bd2 e8 bd 28 1c 00 CALL sprintf int sprintf(char * _Dest, char *
180037bd7 b8 03 00 00 80 MOV status,0x80000003
LAB_180037bdc XREF[2]: 180037c10(j), 180037d4d(j)
180037bdc 48 8b 7c 24 30 MOV heightPadding,qword ptr [RSP + local_28]
180037be1 48 8b 5c 24 70 MOV RBX,qword ptr [RSP + local_res18]
180037be6 4c 8b 64 24 28 MOV R12,qword ptr [RSP + local_30]
180037beb 48 83 c4 40 ADD RSP,0x40
180037bef 41 5f POP R15
180037bf1 41 5e POP R14
180037bf3 5e POP RSI
180037bf4 c3 RET
LAB_180037bf5 XREF[1]: 180037bbf(j)
180037bf5 4c 8b c0 MOV outData,status
180037bf8 49 8b cf MOV param_1,R15
180037bfb 83 fb 10 CMP EBX,0x10
180037bfe 75 12 JNZ LAB_180037c12
180037c00 49 8b d6 MOV inData,R14
180037c03 e8 f8 d9 1b 00 CALL memcpy void * memcpy(void * _Dst, void
180037c08 ff 15 22 7c CALL qword ptr [->KERNEL32.DLL::GetCurrentThreadId]
9d 00
180037c0e 33 c0 XOR status,status
180037c10 eb ca JMP LAB_180037bdc
LAB_180037c12 XREF[1]: 180037bfe(j)
180037c12 33 d2 XOR inData,inData
180037c14 48 89 6c 24 38 MOV qword ptr [RSP + local_20],RBP
180037c19 e8 d2 17 1c 00 CALL memset void * memset(void * _Dst, int _
180037c1e 48 63 c6 MOVSXD status,ESI
180037c21 33 ed XOR EBP,EBP
180037c23 48 89 44 24 60 MOV qword ptr [RSP + local_res8],status
180037c28 85 f6 TEST ESI,ESI
180037c2a 0f 8e 10 01 JLE LAB_180037d40
00 00
180037c30 41 8b c4 MOV status,R12D
180037c33 4c 89 6c 24 20 MOV qword ptr [RSP + local_38],R13
180037c38 2b c7 SUB status,heightPadding
180037c3a 45 33 f6 XOR R14D,R14D
180037c3d 4c 63 e8 MOVSXD R13,status
180037c40 48 8b 44 24 60 MOV status,qword ptr [RSP + local_res8]
180037c45 66 66 66 0f NOP word ptr [RAX + RAX*0x1]
1f 84 00 00
00 00 00
LAB_180037c50 XREF[1]: 180037d35(j)
180037c50 45 33 db XOR R11D,R11D
180037c53 4d 85 ed TEST R13,R13
180037c56 0f 8e d0 00 JLE LAB_180037d2c
00 00
180037c5c 48 63 44 24 78 MOVSXD status,dword ptr [RSP + local_res20]
180037c61 48 8b 4c 24 68 MOV param_1,qword ptr [RSP + local_res10]
180037c66 49 8b fd MOV heightPadding,R13
180037c69 48 0f af c5 IMUL status,RBP
180037c6d 4c 8d 14 41 LEA R10,[param_1 + status*0x2]
LAB_180037c71 XREF[1]: 180037d21(j)
180037c71 45 0f b7 02 MOVZX outData,word ptr [inPixel]
180037c75 83 fb 0a CMP EBX,0xa
180037c78 75 37 JNZ LAB_180037cb1
180037c7a 43 8d 0c 1e LEA param_1,[R14 + R11*0x1]
180037c7e b8 56 55 55 55 MOV status,0x55555556
180037c83 41 81 e0 ff AND outData,0x3ff
03 00 00
180037c8a f7 e9 IMUL param_1
180037c8c 8b c2 MOV status,inData
180037c8e c1 e8 1f SHR status,0x1f
180037c91 03 d0 ADD inData,status
180037c93 48 63 c2 MOVSXD status,inData
180037c96 4d 8d 0c 87 LEA height,[R15 + status*0x4]
180037c9a 8d 04 52 LEA status,[RDX + RDX*0x2]
180037c9d 2b c8 SUB param_1,status
180037c9f 8d 0c 89 LEA param_1,[RCX + RCX*0x4]
180037ca2 8d 0c 4d 02 LEA param_1,[0x2 + param_1*0x2]
00 00 00
180037ca9 41 d3 e0 SHL outData,param_1
180037cac 45 09 01 OR dword ptr [height],outData
180037caf eb 66 JMP LAB_180037d17
LAB_180037cb1 XREF[1]: 180037c78(j)
180037cb1 83 fb 0c CMP EBX,0xc
180037cb4 75 61 JNZ LAB_180037d17
180037cb6 43 8d 04 1e LEA status,[R14 + R11*0x1]
180037cba 41 81 e0 ff AND outData,0xfff
0f 00 00
180037cc1 99 CDQ
180037cc2 83 e2 07 AND inData,0x7
180037cc5 03 c2 ADD status,inData
180037cc7 8b c8 MOV param_1,status
180037cc9 83 e0 07 AND status,0x7
180037ccc 2b c2 SUB status,inData
180037cce c1 f9 03 SAR param_1,0x3
180037cd1 8d 04 40 LEA status,[RAX + RAX*0x2]
180037cd4 48 63 c9 MOVSXD param_1,param_1
180037cd7 c1 e0 02 SHL status,0x2
180037cda 99 CDQ
180037cdb 83 e2 1f AND inData,0x1f
180037cde 03 c2 ADD status,inData
180037ce0 44 8b c8 MOV height,status
180037ce3 83 e0 1f AND status,0x1f
180037ce6 2b c2 SUB status,inData
180037ce8 41 c1 f9 05 SAR height,0x5
180037cec 48 8d 14 49 LEA inData,[RCX + RCX*0x2]
180037cf0 49 63 c9 MOVSXD param_1,height
180037cf3 48 03 d1 ADD inData,param_1
180037cf6 8b c8 MOV param_1,status
180037cf8 4d 8d 0c 97 LEA height,[R15 + inData*0x4]
180037cfc 41 8b d0 MOV inData,outData
180037cff d3 e2 SHL inData,param_1
180037d01 41 09 11 OR dword ptr [height],inData
180037d04 83 f8 14 CMP status,0x14
180037d07 7e 0e JLE LAB_180037d17
180037d09 b9 20 00 00 00 MOV param_1,0x20
180037d0e 2b c8 SUB param_1,status
180037d10 41 d3 e8 SHR outData,param_1
180037d13 45 09 41 04 OR dword ptr [height + 0x4],outData
LAB_180037d17 XREF[3]: 180037caf(j), 180037cb4(j),
180037d07(j)
180037d17 41 ff c3 INC position_
180037d1a 49 83 c2 02 ADD inPixel,0x2
180037d1e 48 ff cf DEC rowsRemaining
180037d21 0f 85 4a ff JNZ LAB_180037c71
ff ff
180037d27 48 8b 44 24 60 MOV status,qword ptr [RSP + local_res8]
LAB_180037d2c XREF[1]: 180037c56(j)
180037d2c 48 ff c5 INC currentPosition
180037d2f 45 03 f4 ADD R14D,R12D
180037d32 48 3b e8 CMP currentPosition,status
180037d35 0f 8c 15 ff JL LAB_180037c50
ff ff
180037d3b 4c 8b 6c 24 20 MOV R13,qword ptr [RSP + local_38]
LAB_180037d40 XREF[1]: 180037c2a(j)
180037d40 48 8b 6c 24 38 MOV currentPosition,qword ptr [RSP + local_20]
180037d45 ff 15 e5 7a CALL qword ptr [->KERNEL32.DLL::GetCurrentThreadId]
9d 00
180037d4b 33 c0 XOR status,status
180037d4d e9 8a fe ff ff JMP LAB_180037bdc
LAB_180037d52 XREF[2]: 180037b0a(j), 180037b13(j)
180037d52 b8 23 00 00 80 MOV status,0x80000023
180037d57 48 83 c4 40 ADD RSP,0x40
180037d5b 41 5f POP R15
180037d5d 41 5e POP R14
180037d5f 5e POP RSI
180037d60 c3 RET
180037d61 cc cc cc cc align align(15)
cc cc cc cc
cc cc cc cc
I may add that it's an AMD64/Intelx64 64bits assembly for Windows 10.

convert hex code (in packet) to UTF-8

sturct ptr info
struct ptr { // packet struct
unsigned long srcip;
unsigned long dstip;
unsigned short srcport;
unsigned short dstport;
unsigned char *str; // payload data of packet
unsigned short len; // payload length
unsigned long ts;
};
find file path and save module code
char *msg = NULL; // to save file path
int j = 0;
/* find file path and save */
for (i=84; i < ptr->len; i++) {
if (ptr->str[i] > 0x00 && ptr->str[i] < 0x7f) {
msg[j] = ptr->str[i];
j++;
}
if (ptr->str[i] > 0x7f) {
msg[j] = 0x23;
j++;
}
}
This is file path in SMB packet, i captured on Wireshark.
0000 5c 00 e0 ac c8 b2 5c 00 73 00 65 00 63 00 72 00 \.....\.s.e.c.r.
0010 65 00 74 00 5c 00 78 c7 ac c0 2e 00 74 00 78 00 e.t.\.x.....t.x.
0020 74 00 00 00 t...
current result =
msg : \####\secret\x###.txt
I just put '#' (0x23) temporarily..
and this is what i want =
msg : \고니\secret\인사.txt
I just found "e0 ac" are part of letter '고' , "c8 b2" are part of letter '니'
But i don't know how to convert..
In sum, i want convert hex code (in packet) to UTF-8.

Reading assembly code with optimization turned on

I've tried to compare output from compiler with and without -O3 option, and I cannot follow how optimized code works.
Here's C code:
#include <stdio.h>
#include <limits.h>
int main(int argc, char *argv[]) {
int a = 3;
int b = argc;
while (b) {
++a;
--b;
}
printf("%d\n", a);
return 0;
}
And this is objdump output without optimization. Looks preety straightforward:
000000000040052d <main>:
#include <stdio.h>
#include <limits.h>
int main(int argc, char *argv[]) {
40052d: 55 push %rbp
40052e: 48 89 e5 mov %rsp,%rbp
400531: 48 83 ec 20 sub $0x20,%rsp
400535: 89 7d ec mov %edi,-0x14(%rbp)
400538: 48 89 75 e0 mov %rsi,-0x20(%rbp)
int a = 3;
40053c: c7 45 f8 03 00 00 00 movl $0x3,-0x8(%rbp)
int b = argc;
400543: 8b 45 ec mov -0x14(%rbp),%eax
400546: 89 45 fc mov %eax,-0x4(%rbp)
while (b) {
400549: eb 08 jmp 400553 <main+0x26>
++a;
40054b: 83 45 f8 01 addl $0x1,-0x8(%rbp)
--b;
40054f: 83 6d fc 01 subl $0x1,-0x4(%rbp)
int main(int argc, char *argv[]) {
int a = 3;
int b = argc;
while (b) {
400553: 83 7d fc 00 cmpl $0x0,-0x4(%rbp)
400557: 75 f2 jne 40054b <main+0x1e>
++a;
--b;
}
printf("%d\n", a);
400559: 8b 45 f8 mov -0x8(%rbp),%eax
40055c: 89 c6 mov %eax,%esi
40055e: bf 04 06 40 00 mov $0x400604,%edi
400563: b8 00 00 00 00 mov $0x0,%eax
400568: e8 a3 fe ff ff callq 400410 <printf#plt>
return 0;
40056d: b8 00 00 00 00 mov $0x0,%eax
}
But after adding -O3 option to gcc I got this:
0000000000400470 <main>:
#include <stdio.h>
#include <limits.h>
int main(int argc, char *argv[]) {
400470: 8d 47 03 lea 0x3(%rdi),%eax
400473: 48 83 ec 08 sub $0x8,%rsp
400477: ba 03 00 00 00 mov $0x3,%edx
40047c: 85 ff test %edi,%edi
}
__fortify_function int
printf (const char *__restrict __fmt, ...)
{
return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());
40047e: be 14 06 40 00 mov $0x400614,%esi
400483: bf 01 00 00 00 mov $0x1,%edi
400488: 0f 45 d0 cmovne %eax,%edx
40048b: 31 c0 xor %eax,%eax
40048d: e8 ce ff ff ff callq 400460 <__printf_chk#plt>
}
printf("%d\n", a);
return 0;
}
400492: 31 c0 xor %eax,%eax
400494: 48 83 c4 08 add $0x8,%rsp
400498: c3 retq
I can't see any jumps, or any effective add, sub instructions except manipulation with stack. Can someone explain this to me?
Thanks
Your code is optimized to printf("%d\n", 3 + argc), because gcc can figure out what the loop does.
The 3+argc is the first lea 0x3(%rdi),%eax.
actually, gcc doesn't quite solve the loop:
The test/cmov stuff seems to be doing:
int a = 3;
if (argc != 0)
a = argc + 3;
aka
int a = argc ? 3 + argc : 3;

Serialization issues while sending struct over socket

I am developing a Client/Server based on UDP I want to send different messages to the client from the server. There are different C structures defined for each message.
I would like to understand what is wrong in the way I am serializing the data.
struct Task
{
int mType;
int tType;
int cCnt;
int* cId;
char data[128];
};
Serialization/Deserialization functions
unsigned char * serialize_int(unsigned char *buffer, int value)
{
buffer[0] = value >> 24;
buffer[1] = value >> 16;
buffer[2] = value >> 8;
buffer[3] = value;
return buffer + 4;
}
unsigned char * serialize_char(unsigned char *buffer, char value)
{
buffer[0] = value;
return buffer + 1;
}
int deserialize_int(unsigned char *buffer)
{
int value = 0;
value |= buffer[0] << 24;
value |= buffer[1] << 16;
value |= buffer[2] << 8;
value |= buffer[3];
return value;
}
char deserialize_char(unsigned char *buffer)
{
return buffer[0];
}
Sender side code to serialize the structure
unsigned char* serializeTask(unsigned char* msg, const Task* t)
{
msg = serialize_int(msg,t->mType);
msg = serialize_int(msg,t->tkType);
msg = serialize_int(msg,t->cCnt);
for(int i=0; i<t->cCnt; i++)
msg = serialize_int(msg,t->cId[i*4]);
for(int i=0; i<strlen(data); i++)
msg = serialize_char(msg,t->data[i]);
return msg;
}
Receiver side code to de-serialize data
printf("Msg type:%d\n", deserialize_int(message) );
printf("Task Type:%d\n", deserialize_int(message+4) );
printf("Task Count:%d\n", deserialize_int(message+8));
Output
Msg type:50364598 //Expected value is 3
Task Type:-2013036362 //Expected value is 1
Task Count:1745191094 //Expected value is 3
Question 1:
Why is the de-serialized value not same as expected?
Question 2:
How is serialization/de-serialization method different from memcpy?
Task t;
memcpy(&t, msg, sizeof(t)); //msg is unsigned char* holding the struct data
EDIT
Code which invokes serializeTask
void addToDatabase(unsigned char* message, int msgSize, Task* task)
{
message = new unsigned char[2*msgSize+1];
unsigned char* msg = message; //To preserve start address of message
message = serializeTask(message, task); //Now message points to end of the array
//Insert serialized data to DB
//msg is inserted to DB
}
Serialized data stored in DB
Message:
00
03 70 B6 88 03 70 B6 68 05 70 B6 68 05 70 B6 00
00 00 00 00 00 00 00 A8 05 70 B6 AC 05 70 B6 B4
05 70 B6 C9 05 70 B6 DE 05 70 B6 E6 05 70 B6 EE
05 70 B6 FB 05 70 B6 64 65 66 00 63 6F 68 6F 72
74 73 00 70 65 6E 64 69 6E 67 5F 61 73 73 69 67
6E 5F 74 61 73 6B 73 00 70 65 6E 64 69 6E 67 5F
61 73 73 69 67 6E 5F 74 61 73 6B 73 00 6D 65 73
73 61 67 65 00 6D 65 73 73 61 67 65 00 3F 00 FF
FF 00 00 FC 90 00 00 00 00 00 00 00 C9 2D B7 00
00 00 00 10 06 70 B6 00 00 00 00 00 00 00 00 30
06 70 B6 34 06 70 B6 3C 06 70 B6
OP has 2 problems in serializeTask()
for(int i=0; i<t->cCnt; i++)
msg = serialize_int(msg,t->cId[i*4]); [i*4]
...
for(int i=0; i<strlen(data); i++)
msg = serialize_char(msg,t->data[i]); strlen(data)
Should be (assuming i<strlen(data) should have been i<strlen(t->data)
for(int i=0; i<t->cCnt; i++)
msg = serialize_int(msg,t->cId[i]); // [i]
...
for(int i=0; i<strlen(t->data); i++) // strlen(data) + 1
msg = serialize_char(msg,t->data[i]);
The first for loop serialize every 4th cId[]. OP certainly wanted to serialize consecutive cId[].
Only the length of the data string was serialized. OP certainly wanted to serialize all that and a NUL terminating byte.
The data in the posted buffer is more likely the below, which does not match the serialization code. This implies the higher level code populating Task* t is wrong. I am confident that the values seen in fields mType and tkType are either pointers or float, again Task* t is likely amiss before the serialization.
0xb6700300 or -3.576453e-06
0xb6700388 or -3.576484e-06
0xb6700568 or -3.576593e-06
0xb6700568 or -3.576593e-06
0x000000 or 0.000000e+00
0x000000 or 0.000000e+00
0xb67005a8 or -3.576608e-06
0xb67005ac or -3.576609e-06
0xb67005b4 or -3.576611e-06
0xb67005c9 or -3.576615e-06
0xb67005de or -3.576620e-06
0xb67005e6 or -3.576622e-06
0xb67005ee or -3.576624e-06
0xb67005fb or -3.576627e-06
def\0cohorts\0pending_assign_tasks\0pending_assign_tasks\0message\0message\0?\0
...

Fill an array in C

I have a question on filling an array with values in C. I have a string that I want to split into an array of new strings each 14 'sections' long.
int main(int argc , char *argv[])
{
char string[]="50 09 00 00 98 30 e0 b1 0d 01 00 00 00 00 4f 09 00 00 98 30 c6 b1 0d 01 01 01 01 50 09 00 00 98 30 e0 b1 0d 01 00 00 00 00 4f 09 00 00 98 30 c6 b1 0d 01 01 01 01";
char delim[] = " ";
char *result = NULL;
char *strArray[1440] = {0};
int i = 0;
result = strtok(string, " ");
while (result)
{
strArray[i] = result;
result = strtok( NULL, delim );
i++;
}
// Now I have each 'section' of the original string in strArray[xx]
int z = 1022;
int c;
char arr[5000];
char *finalarr[100] = {0};
char buff[100];
int l = 0;
for(c=0;c<z;++c)
{
strcat(arr,strArray[c]);
if (c % 14 == 13)
{
// print the value so far for check, this gives an output of 28 chars
puts(arr);
// copy value of arr to buff
ret = sprintf(buff,"%s", arr);
// copy value of buff to instance of finalarr
finalarr[l] = buff;
// empty arr
strcpy(arr," ");
l++;
}
}
// both have the same value (last value of arr)
printf("finalarr1 = %s\n",finalarr[1]);
printf("finalarr20 = %s\n",finalarr[20]);
}
Perhaps I'm trying to solve it in a too complex way (I hope). Anyway some directions to help would be highly appreciated.
#include <stdio.h>
#include <string.h>
int main(int argc , char *argv[])
{
int i;
int fcount=0;
int acount=0;
char string[]="50 09 00 00 98 30 e0 b1 0d 01 00 00 00 00 4f 09 00 00 98 30 c6 b1 0d 01 01 01 01 50 09 00 00 98 30 e0 b1 0d 01 00 00 00 00 4f 09 00 00 98 30 c6 b1 0d 01 01 01 01";
char *finalarr[100];
char arr[29]="\0";
for (i=0;i<(strlen(string));i++)
{
if ((i+1)%3!=0)
{
strncpy(&arr[acount],&string[i],1);
acount++;
if (acount==28)
{
acount=0;
arr[29]="\0";
finalarr[fcount]=strdup(arr);
fcount++;
}
}
}
printf("finalarr1 = %s\n",finalarr[0]);
printf("finalarr1 = %s\n",finalarr[1]);
printf("finalarr1 = %s\n",finalarr[2]);
return 0;
}
result:
finalarr1 = 500900009830e0b10d0100000000
finalarr1 = 4f0900009830c6b10d0101010150
finalarr1 = 0900009830e0b10d01000000004f
You should replace the lines:
// copy value of arr to buff
ret = sprintf(buff,"%s", arr);
// copy value of buff to instance of finalarr
finalarr[l] = buff;
with:
finalarr[l] = strdup(arr);
because you only need to duplicate the string stored in arr. The variable buff should not be needed.
And the line:
// empty arr
strcpy(arr," ");
with:
*arr = '\0';
Because you only need to "reset" the string arr. With your original line, you only "replaced " former text with a 'lonely' space.

Resources