to perform inter segement branching (jump/call) cs needs to be changed
from windbg you can observe kernel code is running in code segment 0x10 while user mode code is running in 0x33 (64 bits) or 0x23 (32 bits)
:\>livekd -b -c rcs;q | findstr "cs="
cs=0010
:\>cdb -c "r cs;q" cdb.exe | findstr "cs="
cs=0033
:\>cd "c:\Program Files (x86)\Windows Kits\10\Debuggers\x86"
:\>.\cdb -c "r cs;q" .\cdb.exe | findstr "cs="
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
cs=00000023
a 32 bit binary when running in a 64 bit windows uses WoW (windows on windows ) layer to run 64 bit code to perform syscalls employing inter segement calls with same privileges but different selector
ntdll!Wow64SystemServiceCall:
77cf8b40 ff252892d977 jmp dword ptr [ntdll!Wow64Transition (77d99228)] ds:002b:77d99228=77c67000
0:000> t
eax=0007000e ebx=00000000 ecx=ffffffff edx=77cf8b40 esi=77d95ce0 edi=77c76a78
eip=77c67000 esp=04a7f510 ebp=04a7f788 iopl=0 nv up ei pl zr na pe nc
>>>cs=0023<<<
ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
77c67000 ea0970c6773300 jmp 0033:77C67009 <<<< calling
EDIT:
the queries you pose in edit are probably worth a few lectures and can't be answered justifiably in Q.A site.
you may need to look for Segment Descriptor , Segment Selector ,
Global Descriptor Table , Local Descriptor Table , Segment Translation
and run through AMD and Intel Manuals a few times to get a grip.
cs , fs, ss, es ,gs ds are segment selectors a 16 bit entity
bit 0,1 denotes Requested Privilege Level or RPL
bit 2 denotes Which Descriptor Table (Table Indicator or TI) to use
( GDT or LDT )
bit 3 to 15 denotes the Index
SELECTORS Dissected
hex | bin | index | TI | RPL |
10 | 0000000000010000 | 0000000000010=0X2 | 0=GDT | 00=R0/KERNEL|
23 | 0000000000100011 | 0000000000100=0X4 | 0=GDT | 11=R3/USER |
33 | 0000000000110011 | 0000000000110=0X6 | 0=GDT | 11=R3/USER |
DUMPING First 8 Global Descriptor Table Entries
0: kd> dpp @gdtr L8
fffff804`43856fb0 00000000`00000000
fffff804`43856fb8 00000000`00000000
fffff804`43856fc0 00209b00`00000000 << 0X2
fffff804`43856fc8 00409300`00000000
fffff804`43856fd0 00cffb00`0000ffff << 0X4
fffff804`43856fd8 00cff300`0000ffff
fffff804`43856fe0 0020fb00`00000000 << 0X6
fffff804`43856fe8 00000000`00000000
using dg command to dissect the raw bytes dumped above
0: kd> dg 0x10
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- ----------------- ----------------- ---------- - -- -- -- -- --------
0010 00000000`00000000 00000000`00000000 Code RE Ac 0 Nb By P Lo 0000029b
0: kd> dg 0x20
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- ----------------- ----------------- ---------- - -- -- -- -- --------
0020 00000000`00000000 00000000`ffffffff Code RE Ac 3 Bg Pg P Nl 00000cfb
0: kd> dg 0x30
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- ----------------- ----------------- ---------- - -- -- -- -- --------
0030 00000000`00000000 00000000`00000000 Code RE Ac 3 Nb By P Lo 000002fb
0: kd>
so between selector 4 and 6 or cs = 0x23 and cs = 0x33
difference in both cs selector is in 0x33 Long Mode or 64 bit code execution is possible
whereas with cs = 0x23 executing 64 bit instruction is not possible
a practical usage can be observed below in the disassembly of same bytes between cs changes
0:000:x86> ? cs
Evaluate expression: 35 = 00000023
0:000:x86> $$ cs is now in 2 bit mode and disassembly will be as x86 see prompt also
0:000:x86> u . l4
wow64cpu!KiFastSystemCall:
77c67000 ea0970c6773300 jmp 0033:77C67009
77c67007 0000 add byte ptr [eax],al
77c67009 41 inc ecx
77c6700a ffa7f8000000 jmp dword ptr [edi+0F8h]
0:000:x86> $$ lets single step
0:000:x86> t
wow64cpu!KiFastSystemCall+0x9:
00000000`77c67009 41ffa7f8000000 jmp qword ptr [r15+0F8h] ds:00000000`77c64758={wow64cpu!CpupReturnFromSimulatedCode (00000000`77c61782)}
0:000> $$ see the x86 garbage disassembly has now a meaningful x64 instruction
0:000> $$ and prompt is not x86 anymore but x64
0:000> u .-9 l6
wow64cpu!KiFastSystemCall:
00000000`77c67000 ea ???
00000000`77c67001 0970c6 or dword ptr [rax-3Ah],esi
00000000`77c67004 7733 ja wow64cpu!KiFastSystemCall+0x39 (00000000`77c67039)
00000000`77c67006 0000 add byte ptr [rax],al
00000000`77c67008 0041ff add byte ptr [rcx-1],al
00000000`77c6700b a7 cmps dword ptr [rsi],dword ptr [rdi]
0:000> disassembling x86 code as x64 results ingarbage now