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.