about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--example/jitter/unpack_upx.py4
-rw-r--r--example/symbol_exec/dse_crackme.py7
-rw-r--r--miasm/analysis/sandbox.py20
-rw-r--r--miasm/core/utils.py16
-rw-r--r--miasm/jitter/jitload.py41
-rw-r--r--miasm/jitter/loader/elf.py2
-rw-r--r--miasm/jitter/loader/pe.py147
-rw-r--r--miasm/jitter/loader/utils.py23
-rw-r--r--miasm/os_dep/common.py35
-rw-r--r--miasm/os_dep/linux/syscall.py32
-rw-r--r--miasm/os_dep/linux_stdlib.py20
-rw-r--r--miasm/os_dep/win_api_x86_32.py297
-rw-r--r--miasm/os_dep/win_api_x86_32_seh.py6
-rw-r--r--test/arch/x86/qemu/testqemu.py6
-rw-r--r--test/arch/x86/qemu/testqemu64.py6
-rwxr-xr-xtest/os_dep/linux/stdlib.py2
-rwxr-xr-xtest/os_dep/win_api_x86_32.py9
17 files changed, 393 insertions, 280 deletions
diff --git a/example/jitter/unpack_upx.py b/example/jitter/unpack_upx.py
index 3b8125f4..baa6f0bb 100644
--- a/example/jitter/unpack_upx.py
+++ b/example/jitter/unpack_upx.py
@@ -5,6 +5,8 @@ from pdb import pm
 from miasm.loader import pe
 from miasm.analysis.sandbox import Sandbox_Win_x86_32
 
+from miasm.os_dep.common import get_win_str_a
+
 # User defined methods
 
 def kernel32_GetProcAddress(jitter):
@@ -17,7 +19,7 @@ def kernel32_GetProcAddress(jitter):
 
     # Handle ordinal imports
     fname = (args.fname if args.fname < 0x10000
-             else jitter.get_str_ansi(args.fname))
+             else get_win_str_a(jitter, args.fname))
     logging.error(fname)
 
     # Get the generated address of the library, and store it in memory to
diff --git a/example/symbol_exec/dse_crackme.py b/example/symbol_exec/dse_crackme.py
index be9f4490..82a7af08 100644
--- a/example/symbol_exec/dse_crackme.py
+++ b/example/symbol_exec/dse_crackme.py
@@ -20,6 +20,7 @@ from miasm.core.utils import int_to_byte
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
 from miasm.analysis.sandbox import Sandbox_Linux_x86_64
 from miasm.expression.expression import *
+from miasm.os_dep.win_api_x86_32 import get_win_str_a
 
 is_win = platform.system() == "Windows"
 
@@ -37,7 +38,7 @@ def xxx_fopen(jitter):
     '''
     global my_FILE_ptr
     ret_addr, args = jitter.func_args_systemv(['path', 'mode'])
-    fname = jitter.get_str_ansi(args.path)
+    fname = get_win_str_a(jitter, args.path)
     FILE_to_info[my_FILE_ptr] = FInfo(fname, open(fname, "rb"))
     my_FILE_ptr += 1
     return jitter.func_ret_stdcall(ret_addr, my_FILE_ptr - 1)
@@ -139,7 +140,7 @@ def xxx_fopen_symb(dse):
     mode = dse.eval_expr(regs.RSI)
     assert fname_addr.is_int()
     assert mode.is_int()
-    fname = dse.jitter.get_str_ansi(int(fname_addr))
+    fname = get_win_str_a(dse.jitter, int(fname_addr))
     ret_addr = ExprInt(dse.jitter.get_stack_arg(0), regs.RIP.size)
 
     assert len(FILE_to_info_symb) == 0
@@ -223,7 +224,7 @@ class FinishOn(Exception):
         super(FinishOn, self).__init__()
 
 def xxx_puts_symb(dse):
-    string = dse.jitter.get_str_ansi(dse.jitter.cpu.RDI)
+    string = get_win_str_a(dse.jitter, dse.jitter.cpu.RDI)
     raise FinishOn(string)
 
 
diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py
index b8aaf788..3040a1a8 100644
--- a/miasm/analysis/sandbox.py
+++ b/miasm/analysis/sandbox.py
@@ -6,13 +6,13 @@ import logging
 from argparse import ArgumentParser
 
 from future.utils import viewitems, viewvalues
+from past.builtins import basestring
 
-from miasm.core.utils import force_bytes
 from miasm.analysis.machine import Machine
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
 from miasm.analysis import debugging
 from miasm.jitter.jitload import log_func
-
+from miasm.core.utils import force_bytes
 
 
 class Sandbox(object):
@@ -51,8 +51,7 @@ class Sandbox(object):
         """
 
         # Initialize
-        if not isinstance(fname, bytes):
-            fname = fname.encode('utf8')
+        assert isinstance(fname, basestring)
         self.fname = fname
         self.options = options
         if custom_methods is None:
@@ -183,17 +182,18 @@ class Arch(object):
 
 class OS_Win(OS):
     # DLL to import
-    ALL_IMP_DLL = ["ntdll.dll", "kernel32.dll", "user32.dll",
-                   "ole32.dll", "urlmon.dll",
-                   "ws2_32.dll", 'advapi32.dll', "psapi.dll",
-                   ]
-    modules_path = b"win_dll"
+    ALL_IMP_DLL = [
+        "ntdll.dll", "kernel32.dll", "user32.dll",
+        "ole32.dll", "urlmon.dll",
+        "ws2_32.dll", 'advapi32.dll', "psapi.dll",
+    ]
+    modules_path = "win_dll"
 
     def __init__(self, custom_methods, *args, **kwargs):
         from miasm.jitter.loader.pe import vm_load_pe, vm_load_pe_libs,\
             preload_pe, libimp_pe, vm_load_pe_and_dependencies
         from miasm.os_dep import win_api_x86_32, win_api_x86_32_seh
-        methods = dict((name.encode(),func) for name, func in viewitems(win_api_x86_32.__dict__))
+        methods = dict((name, func) for name, func in viewitems(win_api_x86_32.__dict__))
         methods.update(custom_methods)
 
         super(OS_Win, self).__init__(methods, *args, **kwargs)
diff --git a/miasm/core/utils.py b/miasm/core/utils.py
index 9856d4f2..7667a656 100644
--- a/miasm/core/utils.py
+++ b/miasm/core/utils.py
@@ -1,4 +1,5 @@
 from __future__ import print_function
+import sys
 from builtins import range
 import struct
 import inspect
@@ -86,6 +87,21 @@ def force_bytes(value):
         return value
 
 
+def force_str(value):
+    if isinstance(value, str):
+        return value
+    elif isinstance(value, bytes):
+        out = ""
+        for i in range(len(value)):
+            # For Python2/Python3 compatibility
+            c = ord(value[i:i+1])
+            out += chr(c)
+        value = out
+    else:
+        raise ValueError("Unsupported type")
+    return value
+
+
 def iterbytes(string):
     for i in range(len(string)):
         yield string[i:i+1]
diff --git a/miasm/jitter/jitload.py b/miasm/jitter/jitload.py
index 9fcb0b0a..e8277e34 100644
--- a/miasm/jitter/jitload.py
+++ b/miasm/jitter/jitload.py
@@ -429,8 +429,8 @@ class Jitter(object):
         return self.cpu.get_exception() | self.vm.get_exception()
 
     # commun functions
-    def get_str_ansi(self, addr, max_char=None):
-        """Get ansi str from vm.
+    def get_c_str(self, addr, max_char=None):
+        """Get C str from vm.
         @addr: address in memory
         @max_char: maximum len"""
         l = 0
@@ -440,31 +440,21 @@ class Jitter(object):
             tmp += 1
             l += 1
         value = self.vm.get_mem(addr, l)
-        return value.decode('utf8')
+        value = force_str(value)
+        return value
 
-    def get_str_unic(self, addr, max_char=None):
-        """Get unicode str from vm.
+    def set_c_str(self, addr, value):
+        """Set C str str from vm.
         @addr: address in memory
-        @max_char: maximum len"""
-        l = 0
-        tmp = addr
-        while ((max_char is None or l < max_char) and
-               self.vm.get_mem(tmp, 2) != b"\x00\x00"):
-            tmp += 2
-            l += 2
-        s = self.vm.get_mem(addr, l)
-        s = s.decode("utf-16le")
-        return s
-
-    def set_str_ansi(self, addr, string):
-        """Set an ansi string in memory"""
-        string = (string + "\x00").encode('utf8')
-        self.vm.set_mem(addr, string)
-
-    def set_str_unic(self, addr, string):
-        """Set an unicode string in memory"""
-        s = (string + "\x00").encode('utf-16le')
-        self.vm.set_mem(addr, s)
+        @value: str"""
+        value = force_bytes(value)
+        self.vm.set_mem(addr, value + b'\x00')
+
+    def get_str_ansi(self, addr, max_char=None):
+        raise NotImplementedError("Deprecated: use os_dep.win_api_x86_32.get_win_str_a")
+
+    def get_str_unic(self, addr, max_char=None):
+        raise NotImplementedError("Deprecated: use os_dep.win_api_x86_32.get_win_str_a")
 
     @staticmethod
     def handle_lib(jitter):
@@ -501,7 +491,6 @@ class Jitter(object):
         self.libs = libs
         out = {}
         for name, func in viewitems(user_globals):
-            name = force_bytes(name)
             out[name] = func
         self.user_globals = out
 
diff --git a/miasm/jitter/loader/elf.py b/miasm/jitter/loader/elf.py
index b70872df..65d96001 100644
--- a/miasm/jitter/loader/elf.py
+++ b/miasm/jitter/loader/elf.py
@@ -9,6 +9,7 @@ import miasm.loader.elf as elf_csts
 
 from miasm.jitter.csts import *
 from miasm.jitter.loader.utils import canon_libname_libfunc, libimp
+from miasm.core.utils import force_str
 from miasm.core.interval import interval
 
 import logging
@@ -26,6 +27,7 @@ def get_import_address_elf(e):
         if not hasattr(sh, 'rel'):
             continue
         for k, v in viewitems(sh.rel):
+            k = force_str(k)
             import2addr[('xxx', k)].add(v.offset)
     return import2addr
 
diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py
index c779f508..09319664 100644
--- a/miasm/jitter/loader/pe.py
+++ b/miasm/jitter/loader/pe.py
@@ -12,6 +12,7 @@ from miasm.loader import *
 
 from miasm.jitter.csts import *
 from miasm.jitter.loader.utils import canon_libname_libfunc, libimp
+from miasm.core.utils import force_str
 
 log = logging.getLogger('loader_pe')
 hnd = logging.StreamHandler()
@@ -29,7 +30,27 @@ def get_pe_dependencies(pe_obj):
     out = set()
     for dependency in pe_obj.DirImport.impdesc:
         libname = dependency.dlldescname.name.lower()
+        # transform bytes to chr
+        if isinstance(libname, bytes):
+            libname_str = ''
+            for c in libname:
+                libname_str += chr(c)
+            libname = libname_str
         out.add(libname)
+
+    # If binary has redirected export, add dependencies
+    if pe_obj.DirExport.expdesc != None:
+        addrs = get_export_name_addr_list(pe_obj)
+        for imp_ord_or_name, ad in addrs:
+            # if export is a redirection, search redirected dll
+            # and get function real addr
+            ret = is_redirected_export(pe_obj, ad)
+            if ret is False:
+                continue
+            dllname, func_info = ret
+            dllname = dllname + '.dll'
+            out.add(dllname)
+
     return out
 
 
@@ -40,10 +61,11 @@ def get_import_address_pe(e):
     for s in e.DirImport.impdesc:
         # fthunk = e.rva2virt(s.firstthunk)
         # l = "%2d %-25s %s" % (i, repr(s.dlldescname), repr(s))
-        libname = s.dlldescname.name.lower()
+        libname = force_str(s.dlldescname.name.lower())
+
         for ii, imp in enumerate(s.impbynames):
             if isinstance(imp, pe.ImportByName):
-                funcname = imp.name
+                funcname = force_str(imp.name)
             else:
                 funcname = imp
             # l = "    %2d %-16s" % (ii, repr(funcname))
@@ -59,6 +81,7 @@ def preload_pe(vm, e, runtime_lib, patch_vm_imp=True):
     # log.debug('imported funcs: %s' % fa)
     for (libname, libfunc), ads in viewitems(fa):
         for ad in ads:
+            libname = force_str(libname)
             ad_base_lib = runtime_lib.lib_get_add_base(libname)
             ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad)
 
@@ -88,11 +111,12 @@ def is_redirected_export(pe_obj, addr):
     addr_end = pe_obj.virt.find(b'\x00', addr)
     data = pe_obj.virt.get(addr, addr_end)
 
-    dllname, func_info = data.split(b'.', 1)
+    data = force_str(data)
+    dllname, func_info = data.split('.', 1)
     dllname = dllname.lower()
 
     # Test if function is forwarded using ordinal
-    if func_info.startswith(b'#'):
+    if func_info.startswith('#'):
         func_info = int(func_info[1:])
     return dllname, func_info
 
@@ -102,7 +126,7 @@ def get_export_name_addr_list(e):
     # add func name
     for i, n in enumerate(e.DirExport.f_names):
         addr = e.DirExport.f_address[e.DirExport.f_nameordinals[i].ordinal]
-        f_name = n.name.name
+        f_name = force_str(n.name.name)
         # log.debug('%s %s' % (f_name, hex(e.rva2virt(addr.rva))))
         out.append((f_name, e.rva2virt(addr.rva)))
 
@@ -268,8 +292,7 @@ def vm_load_pe_libs(vm, libs_name, libs, lib_path_base, **kargs):
     """
     out = {}
     for fname in libs_name:
-        if not isinstance(fname, bytes):
-            fname = fname.encode('utf8')
+        assert isinstance(fname, str)
         out[fname] = vm_load_pe_lib(vm, fname, libs, lib_path_base, **kargs)
     return out
 
@@ -371,6 +394,27 @@ class libimp_pe(libimp):
         # dependency -> redirector
         self.created_redirected_imports = {}
 
+
+    def add_function(self, dllname, imp_ord_or_name, addr):
+        assert isinstance(dllname, str)
+        assert isinstance(imp_ord_or_name, (int, str))
+        libad = self.name2off[dllname]
+        c_name = canon_libname_libfunc(
+            dllname, imp_ord_or_name
+        )
+        update_entry = True
+        if addr in self.fad2info:
+            known_libad, known_imp_ord_or_name = self.fad2info[addr]
+            if isinstance(imp_ord_or_name, int):
+                update_entry = False
+        self.cname2addr[c_name] = addr
+        log.debug("Add func %s %s", hex(addr), c_name)
+        if update_entry:
+            log.debug("Real Add func %s %s", hex(addr), c_name)
+            self.fad2cname[addr] = c_name
+            self.fad2info[addr] = libad, imp_ord_or_name
+
+
     def add_export_lib(self, e, name):
         if name in self.created_redirected_imports:
             log.error("%r has previously been created due to redirect\
@@ -397,7 +441,7 @@ class libimp_pe(libimp):
             self.libbase_ad += 0x1000
 
             ads = get_export_name_addr_list(e)
-            todo = ads
+            todo = list(ads)
             # done = []
             while todo:
                 # for imp_ord_or_name, ad in ads:
@@ -408,15 +452,19 @@ class libimp_pe(libimp):
                 ret = is_redirected_export(e, ad)
                 if ret:
                     exp_dname, exp_fname = ret
-                    exp_dname = exp_dname + b'.dll'
+                    exp_dname = exp_dname + '.dll'
                     exp_dname = exp_dname.lower()
                     # if dll auto refes in redirection
                     if exp_dname == name:
                         libad_tmp = self.name2off[exp_dname]
-                        if not exp_fname in self.lib_imp2ad[libad_tmp]:
-                            # schedule func
-                            todo = [(imp_ord_or_name, ad)] + todo
-                            continue
+                        if isinstance(exp_fname, str):
+                            exp_fname = bytes(ord(c) for c in exp_fname)
+                        found = None
+                        for tmp_func, tmp_addr in ads:
+                            if tmp_func == exp_fname:
+                                found = tmp_addr
+                        assert found is not None
+                        ad = found
                     else:
                         # import redirected lib from non loaded dll
                         if not exp_dname in self.name2off:
@@ -428,8 +476,8 @@ class libimp_pe(libimp):
                         # Ensure function entry is created
                         _ = self.lib_get_add_func(new_lib_base, exp_fname)
 
-                    libad_tmp = self.name2off[exp_dname]
-                    ad = self.lib_imp2ad[libad_tmp][exp_fname]
+                        libad_tmp = self.name2off[exp_dname]
+                        ad = self.lib_imp2ad[libad_tmp][exp_fname]
 
                 self.lib_imp2ad[libad][imp_ord_or_name] = ad
                 name_inv = dict(
@@ -543,17 +591,59 @@ def vm_load_pe_and_dependencies(vm, fname, name2module, runtime_lib,
         todo += [(name, os.path.join(lib_path_base, name), weight - 1)
                  for name in new_dependencies]
 
-    ordered_modules = sorted(viewitems(weight2name))
-    for _, modules in ordered_modules:
-        for name in modules:
-            pe_obj = name2module[name]
-            if pe_obj is None:
-                continue
-            # Fix imports
-            if pe_obj.DirExport:
-                runtime_lib.add_export_lib(pe_obj, name)
+    known_export_addresses = {}
+    to_resolve = {}
+    for name, pe_obj in name2module.items():
+        print(name)
+        if pe_obj is None:
+            continue
+        if pe_obj.DirExport.expdesc == None:
+            continue
+        addrs = get_export_name_addr_list(pe_obj)
+        for imp_ord_or_name, ad in addrs:
+            # if export is a redirection, search redirected dll
+            # and get function real addr
+            ret = is_redirected_export(pe_obj, ad)
+            if ret is False:
+                known_export_addresses[(name, imp_ord_or_name)] = ad
+            else:
+                dllname, func_info = ret
+                dllname = dllname + '.dll'
+                to_resolve[(name, imp_ord_or_name)] = (dllname, func_info)
+
+    modified = True
+    while modified:
+        modified = False
+        out = {}
+        for target, dependency in to_resolve.items():
+            dllname, funcname = dependency
+            if dependency in known_export_addresses:
+                known_export_addresses[target] = known_export_addresses[dependency]
+                modified = True
+            else:
+                log.error("Cannot resolve redirection %r %r", dllname, dependency)
+                raise RuntimeError('Cannot resolve redirection')
+        to_resolve = out
 
-    for pe_obj in viewvalues(name2module):
+    for dllname, pe_obj in name2module.items():
+        if pe_obj is None:
+            continue
+        ad = pe_obj.NThdr.ImageBase
+        libad = ad
+        runtime_lib.name2off[dllname] = ad
+        runtime_lib.libbase2lastad[ad] = ad + 0x1
+        runtime_lib.lib_imp2ad[ad] = {}
+        runtime_lib.lib_imp2dstad[ad] = {}
+        runtime_lib.libbase_ad += 0x1000
+
+    for (dllname, imp_ord_or_name), addr in known_export_addresses.items():
+        runtime_lib.add_function(dllname, imp_ord_or_name, addr)
+        libad = runtime_lib.name2off[dllname]
+        runtime_lib.lib_imp2ad[libad][imp_ord_or_name] = addr
+
+    assert not to_resolve
+
+    for dllname, pe_obj in name2module.items():
         if pe_obj is None:
             continue
         preload_pe(vm, pe_obj, runtime_lib, patch_vm_imp=True)
@@ -561,9 +651,10 @@ def vm_load_pe_and_dependencies(vm, fname, name2module, runtime_lib,
     return name2module
 
 # machine -> arch
-PE_machine = {0x14c: "x86_32",
-              0x8664: "x86_64",
-              }
+PE_machine = {
+    0x14c: "x86_32",
+    0x8664: "x86_64",
+}
 
 
 def guess_arch(pe):
diff --git a/miasm/jitter/loader/utils.py b/miasm/jitter/loader/utils.py
index 375424e6..d03adc8a 100644
--- a/miasm/jitter/loader/utils.py
+++ b/miasm/jitter/loader/utils.py
@@ -2,24 +2,23 @@ from builtins import int as int_types
 import logging
 
 from future.utils import viewitems, viewvalues
-
-from miasm.core.utils import force_bytes
+from past.builtins import basestring
 
 log = logging.getLogger('loader_common')
 hnd = logging.StreamHandler()
 hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s"))
 log.addHandler(hnd)
-log.setLevel(logging.INFO)
+log.setLevel(logging.DEBUG)
 
 
 def canon_libname_libfunc(libname, libfunc):
-    libname = force_bytes(libname)
-    dn = libname.split(b'.')[0]
+    assert isinstance(libname, basestring)
+    assert isinstance(libfunc, basestring) or isinstance(libfunc, int)
+    dn = libname.split('.')[0]
     if isinstance(libfunc, int_types):
         return str(dn), libfunc
     else:
-        libfunc = force_bytes(libfunc)
-        return b"%s_%s" % (dn, libfunc)
+        return "%s_%s" % (dn, libfunc)
 
 
 class libimp(object):
@@ -37,11 +36,11 @@ class libimp(object):
         self.fake_libs = set()
 
     def lib_get_add_base(self, name):
-        name = force_bytes(name)
-        name = name.lower().strip(b' ')
-        if not b"." in name:
+        assert isinstance(name, basestring)
+        name = name.lower().strip(' ')
+        if not "." in name:
             log.debug('warning adding .dll to modulename')
-            name += b'.dll'
+            name += '.dll'
             log.debug(name)
 
         if name in self.name2off:
@@ -74,7 +73,7 @@ class libimp(object):
 
         if imp_ord_or_name in self.lib_imp2ad[libad]:
             return self.lib_imp2ad[libad][imp_ord_or_name]
-        # log.debug('new imp %s %s' % (imp_ord_or_name, dst_ad))
+        log.debug('new imp %s %s' % (imp_ord_or_name, dst_ad))
         ad = self.libbase2lastad[libad]
         self.libbase2lastad[libad] += 0x10  # arbitrary
         self.lib_imp2ad[libad][imp_ord_or_name] = ad
diff --git a/miasm/os_dep/common.py b/miasm/os_dep/common.py
index 0b4d7e11..4a92ef2a 100644
--- a/miasm/os_dep/common.py
+++ b/miasm/os_dep/common.py
@@ -2,25 +2,27 @@ import os
 
 from future.utils import viewitems
 
-from miasm.core.utils import force_bytes
+from miasm.core.utils import force_bytes, force_str
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
 from miasm.core.utils import get_caller_name
 from miasm.core.utils import pck64, upck64
 
 BASE_SB_PATH = "file_sb"
+WIN_CODEPAGE = "cp1252"
 
-
-def get_str_ansi(jitter, ad_str, max_char=None):
+def get_win_str_a(jitter, ad_str, max_char=None):
     l = 0
     tmp = ad_str
     while ((max_char is None or l < max_char) and
            jitter.vm.get_mem(tmp, 1) != b"\x00"):
         tmp += 1
         l += 1
-    return jitter.vm.get_mem(ad_str, l)
+    data = jitter.vm.get_mem(ad_str, l)
+    ret = data.decode(WIN_CODEPAGE)
+    return ret
 
 
-def get_str_unic(jitter, ad_str, max_char=None):
+def get_win_str_w(jitter, ad_str, max_char=None):
     l = 0
     tmp = ad_str
     while ((max_char is None or l < max_char) and
@@ -31,18 +33,23 @@ def get_str_unic(jitter, ad_str, max_char=None):
     s = s.decode("utf-16le")
     return s
 
+def encode_win_str_a(value):
+    value = value.encode(WIN_CODEPAGE) + b"\x00"
+    return value
+
+def encode_win_str_w(value):
+    value = value.encode("utf-16le") + b'\x00' * 2
+    return value
+
 
-def set_str_ansi(value):
-    value = force_bytes(value)
-    return value + b"\x00"
+def set_win_str_a(jitter, addr, value):
+    value = encode_win_str_a(value)
+    jitter.vm.set_mem(addr, value)
 
 
-def set_str_unic(value):
-    try:
-        value = value.decode()
-    except AttributeError:
-        pass
-    return value.encode("utf-16le") + b'\x00' * 2
+def set_win_str_w(jitter, addr, value):
+    value = encode_win_str_w(value)
+    jitter.vm.set_mem(addr, value)
 
 
 class heap(object):
diff --git a/miasm/os_dep/linux/syscall.py b/miasm/os_dep/linux/syscall.py
index 7fede9f1..01b1687c 100644
--- a/miasm/os_dep/linux/syscall.py
+++ b/miasm/os_dep/linux/syscall.py
@@ -154,7 +154,7 @@ def sys_arml_newuname(jitter, linux_env):
 def sys_generic_access(jitter, linux_env):
     # Parse arguments
     pathname, mode = jitter.syscall_args_systemv(2)
-    rpathname = jitter.get_str_ansi(pathname)
+    rpathname = jitter.get_c_str(pathname)
     rmode = mode
     if mode == 1:
         rmode = "F_OK"
@@ -173,7 +173,7 @@ def sys_generic_access(jitter, linux_env):
 def sys_x86_64_openat(jitter, linux_env):
     # Parse arguments
     dfd, filename, flags, mode = jitter.syscall_args_systemv(4)
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_openat(%x, %r, %x, %x)", dfd, rpathname, flags, mode)
 
     # Stub
@@ -184,7 +184,7 @@ def sys_x86_64_openat(jitter, linux_env):
 def sys_x86_64_newstat(jitter, linux_env):
     # Parse arguments
     filename, statbuf = jitter.syscall_args_systemv(2)
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_newstat(%r, %x)", rpathname, statbuf)
 
     # Stub
@@ -201,7 +201,7 @@ def sys_x86_64_newstat(jitter, linux_env):
 def sys_arml_stat64(jitter, linux_env):
     # Parse arguments
     filename, statbuf = jitter.syscall_args_systemv(2)
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_newstat(%r, %x)", rpathname, statbuf)
 
     # Stub
@@ -229,7 +229,7 @@ def sys_x86_64_writev(jitter, linux_env):
         # };
         iovec = jitter.vm.get_mem(vec + iovec_num * 8 * 2, 8*2)
         iov_base, iov_len = struct.unpack("QQ", iovec)
-        fdesc.write(jitter.get_str_ansi(iov_base)[:iov_len])
+        fdesc.write(jitter.get_c_str(iov_base)[:iov_len])
 
     jitter.syscall_ret_systemv(vlen)
 
@@ -248,7 +248,7 @@ def sys_arml_writev(jitter, linux_env):
         # };
         iovec = jitter.vm.get_mem(vec + iovec_num * 4 * 2, 4*2)
         iov_base, iov_len = struct.unpack("II", iovec)
-        fdesc.write(jitter.get_str_ansi(iov_base)[:iov_len])
+        fdesc.write(jitter.get_c_str(iov_base)[:iov_len])
 
     jitter.syscall_ret_systemv(vlen)
 
@@ -433,7 +433,7 @@ def sys_x86_64_statfs(jitter, linux_env):
     # Parse arguments
     pathname = jitter.cpu.RDI
     buf = jitter.cpu.RSI
-    rpathname = jitter.get_str_ansi(pathname)
+    rpathname = jitter.get_c_str(pathname)
     log.debug("sys_statfs(%r, %x)", rpathname, buf)
 
     # Stub
@@ -486,7 +486,7 @@ def sys_arml_ioctl(jitter, linux_env):
 def sys_generic_open(jitter, linux_env):
     # Parse arguments
     filename, flags, mode = jitter.syscall_args_systemv(3)
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_open(%r, %x, %x)", rpathname, flags, mode)
     # Stub
     # 'mode' is ignored
@@ -569,7 +569,7 @@ def sys_x86_64_newlstat(jitter, linux_env):
     # Parse arguments
     filename = jitter.cpu.RDI
     statbuf = jitter.cpu.RSI
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_newlstat(%s, %x)", rpathname, statbuf)
 
     # Stub
@@ -587,7 +587,7 @@ def sys_arml_lstat64(jitter, linux_env):
     # Parse arguments
     filename = jitter.cpu.R0
     statbuf = jitter.cpu.R1
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_newlstat(%s, %x)", rpathname, statbuf)
 
     # Stub
@@ -607,8 +607,8 @@ def sys_x86_64_lgetxattr(jitter, linux_env):
     name = jitter.cpu.RSI
     value = jitter.cpu.RDX
     size = jitter.cpu.R10
-    rpathname = jitter.get_str_ansi(pathname)
-    rname = jitter.get_str_ansi(name)
+    rpathname = jitter.get_c_str(pathname)
+    rname = jitter.get_c_str(name)
     log.debug("sys_lgetxattr(%r, %r, %x, %x)", rpathname, rname, value, size)
 
     # Stub
@@ -622,8 +622,8 @@ def sys_x86_64_getxattr(jitter, linux_env):
     name = jitter.cpu.RSI
     value = jitter.cpu.RDX
     size = jitter.cpu.R10
-    rpathname = jitter.get_str_ansi(pathname)
-    rname = jitter.get_str_ansi(name)
+    rpathname = jitter.get_c_str(pathname)
+    rname = jitter.get_c_str(name)
     log.debug("sys_getxattr(%r, %r, %x, %x)", rpathname, rname, value, size)
 
     # Stub
@@ -646,7 +646,7 @@ def sys_x86_64_connect(jitter, linux_env):
     fd = jitter.cpu.RDI
     uservaddr = jitter.cpu.RSI
     addrlen = jitter.cpu.RDX
-    raddr = jitter.get_str_ansi(uservaddr + 2)
+    raddr = jitter.get_c_str(uservaddr + 2)
     log.debug("sys_connect(%x, %r, %x)", fd, raddr, addrlen)
 
     # Stub
@@ -698,7 +698,7 @@ def sys_x86_64_readlink(jitter, linux_env):
     path = jitter.cpu.RDI
     buf = jitter.cpu.RSI
     bufsize = jitter.cpu.RDX
-    rpath = jitter.get_str_ansi(path)
+    rpath = jitter.get_c_str(path)
     log.debug("sys_readlink(%r, %x, %x)", rpath, buf, bufsize)
 
     # Stub
diff --git a/miasm/os_dep/linux_stdlib.py b/miasm/os_dep/linux_stdlib.py
index 3fa5b02e..348ef9b4 100644
--- a/miasm/os_dep/linux_stdlib.py
+++ b/miasm/os_dep/linux_stdlib.py
@@ -143,7 +143,7 @@ def xxx_puts(jitter):
 
 
 def get_fmt_args(jitter, fmt, cur_arg):
-    return _get_fmt_args(fmt, cur_arg, jitter.get_str_ansi, jitter.get_arg_n_systemv)
+    return _get_fmt_args(fmt, cur_arg, jitter.get_c_str, jitter.get_arg_n_systemv)
 
 
 def xxx_snprintf(jitter):
@@ -153,7 +153,7 @@ def xxx_snprintf(jitter):
     output = get_fmt_args(jitter, fmt, cur_arg)
     output = output[:size - 1]
     ret = len(output)
-    jitter.vm.set_mem(args.string, (output + '\x00').encode('utf8'))
+    jitter.set_c_str(args.string, output)
     return jitter.func_ret_systemv(ret_addr, ret)
 
 
@@ -162,7 +162,7 @@ def xxx_sprintf(jitter):
     cur_arg, fmt = 2, args.fmt
     output = get_fmt_args(jitter, fmt, cur_arg)
     ret = len(output)
-    jitter.vm.set_mem(args.string, (output + '\x00').encode('utf8'))
+    jitter.set_c_str(args.string, output)
     return jitter.func_ret_systemv(ret_addr, ret)
 
 
@@ -177,14 +177,14 @@ def xxx_printf(jitter):
 
 def xxx_strcpy(jitter):
     ret_ad, args = jitter.func_args_systemv(["dst", "src"])
-    str_src = jitter.get_str_ansi(args.src) + '\x00'
-    jitter.vm.set_mem(args.dst, str_src.encode('utf8'))
+    str_src = jitter.get_c_str(args.src)
+    jitter.set_c_str(args.dst, str_src)
     jitter.func_ret_systemv(ret_ad, args.dst)
 
 
 def xxx_strlen(jitter):
     ret_ad, args = jitter.func_args_systemv(["src"])
-    str_src = jitter.get_str_ansi(args.src)
+    str_src = jitter.get_c_str(args.src)
     jitter.func_ret_systemv(ret_ad, len(str_src))
 
 
@@ -201,13 +201,13 @@ def xxx_free(jitter):
 
 def xxx_strcmp(jitter):
     ret_ad, args = jitter.func_args_systemv(["ptr_str1", "ptr_str2"])
-    s1 = jitter.get_str_ansi(args.ptr_str1)
-    s2 = jitter.get_str_ansi(args.ptr_str2)
+    s1 = jitter.get_c_str(args.ptr_str1)
+    s2 = jitter.get_c_str(args.ptr_str2)
     jitter.func_ret_systemv(ret_ad, cmp_elts(s1, s2))
 
 
 def xxx_strncmp(jitter):
     ret_ad, args = jitter.func_args_systemv(["ptr_str1", "ptr_str2", "size"])
-    s1 = jitter.get_str_ansi(args.ptr_str1, args.size)
-    s2 = jitter.get_str_ansi(args.ptr_str2, args.size)
+    s1 = jitter.get_c_str(args.ptr_str1, args.size)
+    s2 = jitter.get_c_str(args.ptr_str2, args.size)
     jitter.func_ret_systemv(ret_ad, cmp_elts(s1, s2))
diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py
index cdf6a48f..051cedb5 100644
--- a/miasm/os_dep/win_api_x86_32.py
+++ b/miasm/os_dep/win_api_x86_32.py
@@ -28,7 +28,7 @@ from io import StringIO
 import time
 import datetime
 
-from future.utils import PY3, viewitems
+from future.utils import PY3, viewitems, viewvalues
 
 try:
     from Crypto.Hash import MD5, SHA
@@ -38,8 +38,10 @@ except ImportError:
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE, PAGE_EXEC
 from miasm.core.utils import pck16, pck32, hexdump, whoami, int_to_byte
 from miasm.os_dep.common import heap, windows_to_sbpath
-from miasm.os_dep.common import set_str_unic, set_str_ansi
+from miasm.os_dep.common import set_win_str_w, set_win_str_a
 from miasm.os_dep.common import get_fmt_args as _get_fmt_args
+from miasm.os_dep.common import get_win_str_a, get_win_str_w
+from miasm.os_dep.common import encode_win_str_a, encode_win_str_w
 from miasm.os_dep.win_api_x86_32_seh import tib_address
 
 log = logging.getLogger("win_api_x86_32")
@@ -144,8 +146,8 @@ class c_winobjs(object):
         self.dw_pid_dummy2 = 0x333
         self.dw_pid_cur = 0x444
         self.module_fname_nux = None
-        self.module_name = b"test.exe"
-        self.module_path = b"c:\\mydir\\" + self.module_name
+        self.module_name = "test.exe"
+        self.module_path = "c:\\mydir\\" + self.module_name
         self.hcurmodule = None
         self.module_filesize = None
         self.getversion = 0x0A280105
@@ -169,7 +171,7 @@ class c_winobjs(object):
             0x80000001: b"hkey_current_user",
             0x80000002: b"hkey_local_machine"
         }
-        self.cur_dir = b"c:\\tmp"
+        self.cur_dir = "c:\\tmp"
 
         self.nt_mdl = {}
         self.nt_mdl_ad = None
@@ -203,7 +205,7 @@ process_list = [
         winobjs.dw_pid_explorer,  # DWORD     th32ParentProcessID;
         0xbeef,  # LONG      pcPriClassBase;
         0x0,  # DWORD     dwFlags;
-        b"dummy1.exe"  # TCHAR     szExeFile[MAX_PATH];
+        "dummy1.exe"  # TCHAR     szExeFile[MAX_PATH];
     ],
     [
         0x40,  # DWORD     dwSize;
@@ -215,7 +217,7 @@ process_list = [
         4,  # DWORD     th32ParentProcessID;
         0xbeef,  # LONG      pcPriClassBase;
         0x0,  # DWORD     dwFlags;
-        b"explorer.exe"  # TCHAR     szExeFile[MAX_PATH];
+        "explorer.exe"  # TCHAR     szExeFile[MAX_PATH];
     ],
 
     [
@@ -228,7 +230,7 @@ process_list = [
         winobjs.dw_pid_explorer,  # DWORD     th32ParentProcessID;
         0xbeef,  # LONG      pcPriClassBase;
         0x0,  # DWORD     dwFlags;
-        b"dummy2.exe"  # TCHAR     szExeFile[MAX_PATH];
+        "dummy2.exe"  # TCHAR     szExeFile[MAX_PATH];
     ],
 
     [
@@ -337,7 +339,7 @@ def kernel32_Process32First(jitter):
 
     pentry = struct.pack(
         'IIIIIIIII', *process_list[0][:-1]
-    ) + process_list[0][-1]
+    ) + (process_list[0][-1] + '\x00').encode('utf8')
     jitter.vm.set_mem(args.ad_pentry, pentry)
     winobjs.toolhelpsnapshot_info[args.s_handle] = 0
 
@@ -354,7 +356,7 @@ def kernel32_Process32Next(jitter):
         ret = 1
         n = winobjs.toolhelpsnapshot_info[args.s_handle]
         pentry = struct.pack(
-            'IIIIIIIII', *process_list[n][:-1]) + process_list[n][-1]
+            'IIIIIIIII', *process_list[n][:-1]) + (process_list[n][-1]+ '\x00').encode('utf8')
         jitter.vm.set_mem(args.ad_pentry, pentry)
     jitter.func_ret_stdcall(ret_ad, ret)
 
@@ -370,7 +372,7 @@ def kernel32_GetVersion(jitter):
     jitter.func_ret_stdcall(ret_ad, winobjs.getversion)
 
 
-def kernel32_GetVersionEx(jitter, str_size, set_str):
+def kernel32_GetVersionEx(jitter, str_size, encode_str):
     ret_ad, args = jitter.func_args_stdcall(["ptr_struct"])
 
     size = jitter.vm.get_u32(args.ptr_struct)
@@ -382,7 +384,7 @@ def kernel32_GetVersionEx(jitter, str_size, set_str):
             0x2,              # min vers
             0xa28,            # build nbr
             0x2,              # platform id
-            set_str("Service pack 4"),
+            encode_str("Service pack 4"),
             3,                # wServicePackMajor
             0,                # wServicePackMinor
             0x100,            # wSuiteMask
@@ -398,9 +400,9 @@ def kernel32_GetVersionEx(jitter, str_size, set_str):
 
 
 kernel32_GetVersionExA = lambda jitter: kernel32_GetVersionEx(jitter, 128,
-                                                              set_str_ansi)
+                                                              encode_win_str_a)
 kernel32_GetVersionExW = lambda jitter: kernel32_GetVersionEx(jitter, 256,
-                                                              set_str_unic)
+                                                              encode_win_str_w)
 
 
 def kernel32_GetPriorityClass(jitter):
@@ -426,10 +428,10 @@ def user32_GetForegroundWindow(jitter):
 def user32_FindWindowA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["pclassname", "pwindowname"])
     if args.pclassname:
-        classname = jitter.get_str_ansi(args.pclassname)
+        classname = get_win_str_a(jitter, args.pclassname)
         log.info("FindWindowA classname %s", classname)
     if args.pwindowname:
-        windowname = jitter.get_str_ansi(args.pwindowname)
+        windowname = get_win_str_a(jitter, args.pwindowname)
         log.info("FindWindowA windowname %s", windowname)
     jitter.func_ret_stdcall(ret_ad, 0)
 
@@ -455,11 +457,11 @@ def advapi32_CryptAcquireContext(jitter, funcname, get_str):
 
 
 def advapi32_CryptAcquireContextA(jitter):
-    advapi32_CryptAcquireContext(jitter, whoami(), jitter.get_str_ansi)
+    advapi32_CryptAcquireContext(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def advapi32_CryptAcquireContextW(jitter):
-    advapi32_CryptAcquireContext(jitter, whoami(), jitter.get_str_unic)
+    advapi32_CryptAcquireContext(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def advapi32_CryptCreateHash(jitter):
@@ -666,11 +668,11 @@ def kernel32_CreateFile(jitter, funcname, get_str):
 
 
 def kernel32_CreateFileA(jitter):
-    kernel32_CreateFile(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_CreateFile(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_CreateFileW(jitter):
-    kernel32_CreateFile(jitter, whoami(), jitter.get_str_unic)
+    kernel32_CreateFile(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_ReadFile(jitter):
@@ -755,9 +757,13 @@ def kernel32_VirtualProtect(jitter):
         old = jitter.vm.get_mem_access(args.lpvoid)
         jitter.vm.set_u32(args.lpfloldprotect, ACCESS_DICT_INV[old])
 
-    for addr in jitter.vm.get_all_memory():
+    print("XXX VIRTUALP")
+    log.warn("set page %x %x", args.lpvoid, args.dwsize)
+    for addr, data in jitter.vm.get_all_memory().items():
+        size = data["size"]
         # Multi-page
-        if args.lpvoid <= addr < args.lpvoid + args.dwsize:
+        if addr <= args.lpvoid < addr + size:
+            log.warn("set page %x %x", addr, ACCESS_DICT[flnewprotect])
             jitter.vm.set_mem_access(addr, ACCESS_DICT[flnewprotect])
 
     jitter.func_ret_stdcall(ret_ad, 1)
@@ -841,11 +847,11 @@ def kernel32_GetModuleFileName(jitter, funcname, set_str):
 
 
 def kernel32_GetModuleFileNameA(jitter):
-    kernel32_GetModuleFileName(jitter, whoami(), jitter.set_str_ansi)
+    kernel32_GetModuleFileName(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetModuleFileNameW(jitter):
-    kernel32_GetModuleFileName(jitter, whoami(), jitter.set_str_unic)
+    kernel32_GetModuleFileName(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_CreateMutex(jitter, funcname, get_str):
@@ -875,11 +881,11 @@ def kernel32_CreateMutex(jitter, funcname, get_str):
 
 
 def kernel32_CreateMutexA(jitter):
-    kernel32_CreateMutex(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_CreateMutex(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_CreateMutexW(jitter):
-    kernel32_CreateMutex(jitter, whoami(), jitter.get_str_unic)
+    kernel32_CreateMutex(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def shell32_SHGetSpecialFolderLocation(jitter):
@@ -900,11 +906,11 @@ def kernel32_SHGetPathFromIDList(jitter, funcname, set_str):
 
 
 def shell32_SHGetPathFromIDListW(jitter):
-    kernel32_SHGetPathFromIDList(jitter, whoami(), jitter.set_str_unic)
+    kernel32_SHGetPathFromIDList(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def shell32_SHGetPathFromIDListA(jitter):
-    kernel32_SHGetPathFromIDList(jitter, whoami(), jitter.set_str_ansi)
+    kernel32_SHGetPathFromIDList(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetLastError(jitter):
@@ -935,11 +941,11 @@ def kernel32_LoadLibrary(jitter, get_str):
 
 
 def kernel32_LoadLibraryA(jitter):
-    kernel32_LoadLibrary(jitter, jitter.get_str_ansi)
+    kernel32_LoadLibrary(jitter, lambda addr, max_char=None:get_win_str_a(jitter, addr, max_char))
 
 
 def kernel32_LoadLibraryW(jitter):
-    kernel32_LoadLibrary(jitter, jitter.get_str_unic)
+    kernel32_LoadLibrary(jitter, lambda addr, max_char=None:get_win_str_w(jitter, addr, max_char))
 
 
 def kernel32_LoadLibraryEx(jitter, get_str):
@@ -954,18 +960,18 @@ def kernel32_LoadLibraryEx(jitter, get_str):
 
 
 def kernel32_LoadLibraryExA(jitter):
-    kernel32_LoadLibraryEx(jitter, jitter.get_str_ansi)
+    kernel32_LoadLibraryEx(jitter, lambda addr, max_char=None:get_win_str_a(jitter, addr, max_char))
 
 
 def kernel32_LoadLibraryExW(jitter):
-    kernel32_LoadLibraryEx(jitter, jitter.get_str_unic)
+    kernel32_LoadLibraryEx(jitter, lambda addr, max_char=None:get_win_str_w(jitter, addr, max_char))
 
 
 def kernel32_GetProcAddress(jitter):
     ret_ad, args = jitter.func_args_stdcall(["libbase", "fname"])
     fname = args.fname
     if fname >= 0x10000:
-        fname = jitter.get_str_ansi(fname, 0x100)
+        fname = jitter.get_c_str(fname, 0x100)
         if not fname:
             fname = None
     if fname is not None:
@@ -995,11 +1001,11 @@ def kernel32_GetModuleHandle(jitter, funcname, get_str):
 
 
 def kernel32_GetModuleHandleA(jitter):
-    kernel32_GetModuleHandle(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_GetModuleHandle(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_GetModuleHandleW(jitter):
-    kernel32_GetModuleHandle(jitter, whoami(), jitter.get_str_unic)
+    kernel32_GetModuleHandle(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_VirtualLock(jitter):
@@ -1049,29 +1055,28 @@ def kernel32_IsWow64Process(jitter):
 def kernel32_GetCommandLine(jitter, set_str):
     ret_ad, _ = jitter.func_args_stdcall(0)
     alloc_addr = winobjs.heap.alloc(jitter, 0x1000)
-    s = set_str('"%s"' % winobjs.module_path)
-    jitter.vm.set_mem(alloc_addr, s)
+    set_str(alloc_addr, '"%s"' % winobjs.module_path)
     jitter.func_ret_stdcall(ret_ad, alloc_addr)
 
 
 def kernel32_GetCommandLineA(jitter):
-    kernel32_GetCommandLine(jitter, set_str_ansi)
+    kernel32_GetCommandLine(jitter, lambda addr, value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetCommandLineW(jitter):
-    kernel32_GetCommandLine(jitter, set_str_unic)
+    kernel32_GetCommandLine(jitter, lambda addr, value: set_win_str_w(jitter, addr, value))
 
 
 def shell32_CommandLineToArgvW(jitter):
     ret_ad, args = jitter.func_args_stdcall(["pcmd", "pnumargs"])
-    cmd = jitter.get_str_unic(args.pcmd)
+    cmd = get_win_str_w(jitter, args.pcmd)
     log.info("CommandLineToArgv %r", cmd)
     tks = cmd.split(' ')
     addr = winobjs.heap.alloc(jitter, len(cmd) * 2 + 4 * len(tks))
     addr_ret = winobjs.heap.alloc(jitter, 4 * (len(tks) + 1))
     o = 0
     for i, t in enumerate(tks):
-        jitter.set_str_unic(addr + o, t)
+        jitter.set_win_str_w(addr + o, t)
         jitter.vm.set_u32(addr_ret + 4 * i, addr + o)
         o += len(t)*2 + 2
 
@@ -1118,7 +1123,7 @@ def cryptdll_MD5Final(jitter):
 def ntdll_RtlInitAnsiString(jitter):
     ret_ad, args = jitter.func_args_stdcall(["ad_ctx", "ad_str"])
 
-    s = jitter.get_str_ansi(args.ad_str)
+    s = get_win_str_a(jitter, args.ad_str)
     l = len(s)
     jitter.vm.set_mem(args.ad_ctx,
                       pck16(l) + pck16(l + 1) + pck32(args.ad_str))
@@ -1286,7 +1291,7 @@ def ntoskrnl_RtlGetVersion(jitter):
                     0x2,  # min vers
                     0x666,  # build nbr
                     0x2,   # platform id
-                    ) + jitter.set_str_unic("Service pack 4")
+                    ) + jitter.set_win_str_w("Service pack 4")
 
     jitter.vm.set_mem(args.ptr_version, s)
     jitter.func_ret_stdcall(ret_ad, 0)
@@ -1378,7 +1383,7 @@ def ntoskrnl_RtlQueryRegistryValues(jitter):
                                              "querytable",
                                              "context",
                                              "environ"])
-    # path = get_str_unic(jitter, args.path)
+    # path = get_win_str_w(jitter, args.path)
     jitter.func_ret_stdcall(ret_ad, 0)
 
 
@@ -1403,51 +1408,51 @@ def my_lstrcmp(jitter, funcname, get_str):
 
 def msvcrt_wcscmp(jitter):
     ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"])
-    s1 = jitter.get_str_unic(args.ptr_str1)
-    s2 = jitter.get_str_unic(args.ptr_str2)
+    s1 = get_win_str_w(jitter, args.ptr_str1)
+    s2 = get_win_str_w(jitter, args.ptr_str2)
     log.debug("%s('%s','%s')" % (whoami(), s1, s2))
     jitter.func_ret_cdecl(ret_ad, cmp(s1, s2))
 
 def msvcrt__wcsicmp(jitter):
     ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"])
-    s1 = jitter.get_str_unic(args.ptr_str1)
-    s2 = jitter.get_str_unic(args.ptr_str2)
+    s1 = get_win_str_w(jitter, args.ptr_str1)
+    s2 = get_win_str_w(jitter, args.ptr_str2)
     log.debug("%s('%s','%s')" % (whoami(), s1, s2))
     jitter.func_ret_cdecl(ret_ad, cmp(s1.lower(), s2.lower()))
 
 def msvcrt__wcsnicmp(jitter):
     ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2", "count"])
-    s1 = jitter.get_str_unic(args.ptr_str1)
-    s2 = jitter.get_str_unic(args.ptr_str2)
+    s1 = get_win_str_w(jitter, args.ptr_str1)
+    s2 = get_win_str_w(jitter, args.ptr_str2)
     log.debug("%s('%s','%s',%d)" % (whoami(), s1, s2, args.count))
     jitter.func_ret_cdecl(ret_ad, cmp(s1.lower()[:args.count], s2.lower()[:args.count]))
 
 def msvcrt_wcsncpy(jitter):
     ret_ad, args = jitter.func_args_cdecl(["dst", "src", "n"])
-    src = jitter.get_str_unic(args.src)
+    src = get_win_str_w(jitter, args.src)
     dst = src[:args.n]
     dst += "\x00\x00" * (args.n-len(dst)+1)
     jitter.vm.set_mem(args.dst, dst)
     jitter.func_ret_cdecl(ret_ad, args.dst)
 
 def kernel32_lstrcmpA(jitter):
-    my_lstrcmp(jitter, whoami(), jitter.get_str_ansi)
+    my_lstrcmp(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_lstrcmpiA(jitter):
-    my_lstrcmp(jitter, whoami(), lambda x: jitter.get_str_ansi(x).lower())
+    my_lstrcmp(jitter, whoami(), lambda x: get_win_str_a(jitter, x).lower())
 
 
 def kernel32_lstrcmpW(jitter):
-    my_lstrcmp(jitter, whoami(), jitter.get_str_unic)
+    my_lstrcmp(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_lstrcmpiW(jitter):
-    my_lstrcmp(jitter, whoami(), lambda x: jitter.get_str_unic(x).lower())
+    my_lstrcmp(jitter, whoami(), lambda x: get_win_str_w(jitter, x).lower())
 
 
 def kernel32_lstrcmpi(jitter):
-    my_lstrcmp(jitter, whoami(), lambda x: jitter.get_str_ansi(x).lower())
+    my_lstrcmp(jitter, whoami(), lambda x: get_win_str_a(jitter, x).lower())
 
 
 def my_strcpy(jitter, funcname, get_str, set_str):
@@ -1459,20 +1464,20 @@ def my_strcpy(jitter, funcname, get_str, set_str):
 
 
 def kernel32_lstrcpyW(jitter):
-    my_strcpy(jitter, whoami(), jitter.get_str_unic, jitter.set_str_unic)
+    my_strcpy(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_lstrcpyA(jitter):
-    my_strcpy(jitter, whoami(), jitter.get_str_ansi, jitter.set_str_ansi)
+    my_strcpy(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_lstrcpy(jitter):
-    my_strcpy(jitter, whoami(), jitter.get_str_ansi, jitter.set_str_ansi)
+    my_strcpy(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 def msvcrt__mbscpy(jitter):
     ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"])
-    s2 = jitter.get_str_unic(args.ptr_str2)
-    jitter.set_str_unic(args.ptr_str1, s2)
+    s2 = get_win_str_w(jitter, args.ptr_str2)
+    jitter.set_win_str_w(args.ptr_str1, s2)
     jitter.func_ret_cdecl(ret_ad, args.ptr_str1)
 
 def msvcrt_wcscpy(jitter):
@@ -1482,11 +1487,11 @@ def msvcrt_wcscpy(jitter):
 def kernel32_lstrcpyn(jitter):
     ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2",
                                              "mlen"])
-    s2 = jitter.get_str_ansi(args.ptr_str2)
+    s2 = get_win_str_a(jitter, args.ptr_str2)
     if len(s2) >= args.mlen:
         s2 = s2[:args.mlen - 1]
     log.info("Copy '%r'", s2)
-    jitter.set_str_ansi(args.ptr_str1, s2)
+    jitter.set_win_str_a(args.ptr_str1, s2)
     jitter.func_ret_stdcall(ret_ad, args.ptr_str1)
 
 
@@ -1499,15 +1504,15 @@ def my_strlen(jitter, funcname, get_str, mylen):
 
 
 def kernel32_lstrlenA(jitter):
-    my_strlen(jitter, whoami(), jitter.get_str_ansi, len)
+    my_strlen(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), len)
 
 
 def kernel32_lstrlenW(jitter):
-    my_strlen(jitter, whoami(), jitter.get_str_unic, len)
+    my_strlen(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), len)
 
 
 def kernel32_lstrlen(jitter):
-    my_strlen(jitter, whoami(), jitter.get_str_ansi, len)
+    my_strlen(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), len)
 
 
 def my_lstrcat(jitter, funcname, get_str, set_str):
@@ -1519,11 +1524,11 @@ def my_lstrcat(jitter, funcname, get_str, set_str):
 
 
 def kernel32_lstrcatA(jitter):
-    my_lstrcat(jitter, whoami(), jitter.get_str_ansi, jitter.set_str_ansi)
+    my_lstrcat(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_lstrcatW(jitter):
-    my_lstrcat(jitter, whoami(), jitter.get_str_unic, jitter.set_str_unic)
+    my_lstrcat(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_GetUserGeoID(jitter):
@@ -1573,11 +1578,11 @@ def my_GetVolumeInformation(jitter, funcname, get_str, set_str):
 
 def kernel32_GetVolumeInformationA(jitter):
     my_GetVolumeInformation(
-        jitter, whoami(), jitter.get_str_ansi, jitter.set_str_ansi)
+        jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetVolumeInformationW(jitter):
-    my_GetVolumeInformation(jitter, whoami(), jitter.get_str_unic, jitter.set_str_unic)
+    my_GetVolumeInformation(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_MultiByteToWideChar(jitter):
@@ -1586,7 +1591,7 @@ def kernel32_MultiByteToWideChar(jitter):
                                              "cbmultibyte",
                                              "lpwidecharstr",
                                              "cchwidechar"])
-    src = jitter.get_str_ansi(args.lpmultibytestr) + '\x00'
+    src = get_win_str_a(jitter, args.lpmultibytestr) + '\x00'
     l = len(src)
 
     src = "\x00".join(list(src))
@@ -1611,15 +1616,15 @@ def my_GetEnvironmentVariable(jitter, funcname, get_str, set_str, mylen):
 
 def kernel32_GetEnvironmentVariableA(jitter):
     my_GetEnvironmentVariable(jitter, whoami(),
-                              jitter.get_str_ansi,
-                              jitter.set_str_ansi,
+                              lambda addr:get_win_str_a(jitter, addr),
+                              lambda addr,value: set_win_str_a(jitter, addr, value),
                               len)
 
 
 def kernel32_GetEnvironmentVariableW(jitter):
     my_GetEnvironmentVariable(jitter, whoami(),
-                              jitter.get_str_unic,
-                              jitter.set_str_ansi,
+                              lambda addr:get_win_str_w(jitter, addr),
+                              lambda addr,value: set_win_str_w(jitter, addr, value),
                               len)
 
 
@@ -1633,11 +1638,11 @@ def my_GetSystemDirectory(jitter, funcname, set_str):
 
 
 def kernel32_GetSystemDirectoryA(jitter):
-    my_GetSystemDirectory(jitter, whoami(), jitter.set_str_ansi)
+    my_GetSystemDirectory(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetSystemDirectoryW(jitter):
-    my_GetSystemDirectory(jitter, whoami(), jitter.set_str_unic)
+    my_GetSystemDirectory(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def my_CreateDirectory(jitter, funcname, get_str):
@@ -1647,11 +1652,11 @@ def my_CreateDirectory(jitter, funcname, get_str):
 
 
 def kernel32_CreateDirectoryW(jitter):
-    my_CreateDirectory(jitter, whoami(), jitter.get_str_unic)
+    my_CreateDirectory(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_CreateDirectoryA(jitter):
-    my_CreateDirectory(jitter, whoami(), jitter.get_str_ansi)
+    my_CreateDirectory(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 
@@ -1669,11 +1674,11 @@ def my_CreateEvent(jitter, funcname, get_str):
 
 
 def kernel32_CreateEventA(jitter):
-    my_CreateEvent(jitter, whoami(), jitter.get_str_ansi)
+    my_CreateEvent(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_CreateEventW(jitter):
-    my_CreateEvent(jitter, whoami(), jitter.get_str_unic)
+    my_CreateEvent(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_WaitForSingleObject(jitter):
@@ -1704,7 +1709,7 @@ def kernel32_SetFileAttributesA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["lpfilename",
                                              "dwfileattributes"])
     if args.lpfilename:
-        # fname = get_str_ansi(jitter, args.lpfilename)
+        # fname = get_win_str_a(jitter, args.lpfilename)
         ret = 1
     else:
         ret = 0
@@ -1789,7 +1794,7 @@ def ntdll_ZwFreeVirtualMemory(jitter):
 
 def ntdll_RtlInitString(jitter):
     ret_ad, args = jitter.func_args_stdcall(["pstring", "source"])
-    s = jitter.get_str_ansi(args.source)
+    s = get_win_str_a(jitter, args.source)
     l = len(s) + 1
     o = struct.pack('HHI', l, l, args.source)
     jitter.vm.set_mem(args.pstring, o)
@@ -1800,7 +1805,7 @@ def ntdll_RtlAnsiStringToUnicodeString(jitter):
     ret_ad, args = jitter.func_args_stdcall(["dst", "src", "alloc_str"])
 
     l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.src, 0x8))
-    s = jitter.get_str_ansi(p_src)
+    s = get_win_str_a(jitter, p_src)
     s = ("\x00".join(s + "\x00"))
     l = len(s) + 1
     if args.alloc_str:
@@ -1822,7 +1827,7 @@ def ntdll_LdrLoadDll(jitter):
 
     l1, l2, p_src = struct.unpack('HHI',
                                   jitter.vm.get_mem(args.modname, 0x8))
-    s = jitter.get_str_unic(p_src)
+    s = get_win_str_w(jitter, p_src)
     libname = s.lower()
 
     ad = winobjs.runtime_dll.lib_get_add_base(libname)
@@ -1834,7 +1839,7 @@ def ntdll_LdrLoadDll(jitter):
 def ntdll_RtlFreeUnicodeString(jitter):
     ret_ad, args = jitter.func_args_stdcall(['src'])
     # l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.src, 0x8))
-    # s = get_str_unic(jitter, p_src)
+    # s = get_win_str_w(jitter, p_src)
     jitter.func_ret_stdcall(ret_ad, 0)
 
 
@@ -1843,7 +1848,7 @@ def ntdll_LdrGetProcedureAddress(jitter):
                                              "opt", "p_ad"])
 
     l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.pfname, 0x8))
-    fname = jitter.get_str_ansi(p_src)
+    fname = get_win_str_a(jitter, p_src)
 
     ad = winobjs.runtime_dll.lib_get_add_func(args.libbase, fname)
     jitter.add_breakpoint(ad, jitter.handle_lib)
@@ -1866,7 +1871,7 @@ def msvcrt_memset(jitter):
 
 def msvcrt_strrchr(jitter):
     ret_ad, args = jitter.func_args_cdecl(['pstr','c'])
-    s = jitter.get_str_ansi(args.pstr)
+    s = get_win_str_a(jitter, args.pstr)
     c = int_to_byte(args.c)
     ret = args.pstr + s.rfind(c)
     log.info("strrchr(%x '%s','%s') = %x" % (args.pstr,s,c,ret))
@@ -1874,7 +1879,7 @@ def msvcrt_strrchr(jitter):
 
 def msvcrt_wcsrchr(jitter):
     ret_ad, args = jitter.func_args_cdecl(['pstr','c'])
-    s = jitter.get_str_unic(args.pstr)
+    s = get_win_str_w(jitter, args.pstr)
     c = int_to_byte(args.c)
     ret = args.pstr + (s.rfind(c)*2)
     log.info("wcsrchr(%x '%s',%s) = %x" % (args.pstr,s,c,ret))
@@ -1907,7 +1912,7 @@ def msvcrt_memcmp(jitter):
 
 def shlwapi_PathFindExtensionA(jitter):
     ret_ad, args = jitter.func_args_stdcall(['path_ad'])
-    path = jitter.get_str_ansi(args.path_ad)
+    path = get_win_str_a(jitter, args.path_ad)
     i = path.rfind('.')
     if i == -1:
         i = args.path_ad + len(path)
@@ -1918,19 +1923,19 @@ def shlwapi_PathFindExtensionA(jitter):
 
 def shlwapi_PathRemoveFileSpecW(jitter):
     ret_ad, args = jitter.func_args_stdcall(['path_ad'])
-    path = jitter.get_str_unic(args.path_ad)
+    path = get_win_str_w(jitter, args.path_ad)
     i = path.rfind('\\')
     if i == -1:
         i = 0
     jitter.vm.set_mem(args.path_ad + i * 2, "\x00\x00")
-    path = jitter.get_str_unic(args.path_ad)
+    path = get_win_str_w(jitter, args.path_ad)
     jitter.func_ret_stdcall(ret_ad, 1)
 
 
 def shlwapi_PathIsPrefixW(jitter):
     ret_ad, args = jitter.func_args_stdcall(['ptr_prefix', 'ptr_path'])
-    prefix = jitter.get_str_unic(args.ptr_prefix)
-    path = jitter.get_str_unic(args.ptr_path)
+    prefix = get_win_str_w(jitter, args.ptr_prefix)
+    path = get_win_str_w(jitter, args.ptr_path)
 
     if path.startswith(prefix):
         ret = 1
@@ -1941,7 +1946,7 @@ def shlwapi_PathIsPrefixW(jitter):
 
 def shlwapi_PathIsDirectoryW(jitter):
     ret_ad, args = jitter.func_args_stdcall(['ptr_path'])
-    fname = jitter.get_str_unic(args.ptr_path)
+    fname = get_win_str_w(jitter, args.ptr_path)
 
     sb_fname = windows_to_sbpath(fname)
 
@@ -1977,24 +1982,24 @@ def shlwapi_PathGetDriveNumber(jitter, funcname, get_str):
 
 
 def shlwapi_PathGetDriveNumberA(jitter):
-    shlwapi_PathGetDriveNumber(jitter, whoami(), jitter.get_str_ansi)
+    shlwapi_PathGetDriveNumber(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def shlwapi_PathGetDriveNumberW(jitter):
-    shlwapi_PathGetDriveNumber(jitter, whoami(), jitter.get_str_unic)
+    shlwapi_PathGetDriveNumber(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def shlwapi_PathIsFileSpecA(jitter):
-    shlwapi_PathIsFileSpec(jitter, whoami(), jitter.get_str_ansi)
+    shlwapi_PathIsFileSpec(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def shlwapi_PathIsFileSpecW(jitter):
-    shlwapi_PathIsFileSpec(jitter, whoami(), jitter.get_str_unic)
+    shlwapi_PathIsFileSpec(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def shlwapi_StrToIntA(jitter):
     ret_ad, args = jitter.func_args_stdcall(['i_str_ad'])
-    i_str = jitter.get_str_ansi(args.i_str_ad)
+    i_str = get_win_str_a(jitter, args.i_str_ad)
     try:
         i = int(i_str)
     except:
@@ -2020,11 +2025,11 @@ def shlwapi_StrToInt64Ex(jitter, funcname, get_str):
 
 
 def shlwapi_StrToInt64ExA(jitter):
-    shlwapi_StrToInt64Ex(jitter, whoami(), jitter.get_str_ansi)
+    shlwapi_StrToInt64Ex(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def shlwapi_StrToInt64ExW(jitter):
-    shlwapi_StrToInt64Ex(jitter, whoami(), jitter.get_str_unic)
+    shlwapi_StrToInt64Ex(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def user32_IsCharAlpha(jitter, funcname, get_str):
@@ -2042,11 +2047,11 @@ def user32_IsCharAlpha(jitter, funcname, get_str):
 
 
 def user32_IsCharAlphaA(jitter):
-    user32_IsCharAlpha(jitter, whoami(), jitter.get_str_ansi)
+    user32_IsCharAlpha(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def user32_IsCharAlphaW(jitter):
-    user32_IsCharAlpha(jitter, whoami(), jitter.get_str_unic)
+    user32_IsCharAlpha(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def user32_IsCharAlphaNumericA(jitter):
@@ -2067,7 +2072,7 @@ def msvcrt_sprintf_str(jitter, get_str):
     return ret_ad, args, get_fmt_args(jitter, fmt, cur_arg, get_str)
 
 def msvcrt_sprintf(jitter):
-    ret_ad, args, output = msvcrt_sprintf_str(jitter, jitter.get_str_ansi)
+    ret_ad, args, output = msvcrt_sprintf_str(jitter, lambda addr:get_win_str_a(jitter, addr))
     ret = len(output)
     log.info("sprintf() = '%s'" % (output))
     jitter.vm.set_mem(args.string, (output + '\x00').encode('utf8'))
@@ -2076,18 +2081,18 @@ def msvcrt_sprintf(jitter):
 def msvcrt_swprintf(jitter):
     ret_ad, args = jitter.func_args_cdecl(['string', 'fmt'])
     cur_arg, fmt = 2, args.fmt
-    output = get_fmt_args(jitter, fmt, cur_arg, jitter.get_str_unic)
+    output = get_fmt_args(jitter, fmt, cur_arg, lambda addr:get_win_str_w(jitter, addr))
     ret = len(output)
-    log.info("swprintf('%s') = '%s'" % (jitter.get_str_unic(args.fmt), output))
+    log.info("swprintf('%s') = '%s'" % (get_win_str_w(jitter, args.fmt), output))
     jitter.vm.set_mem(args.string, output.encode("utf-16le") + b'\x00\x00')
     return jitter.func_ret_cdecl(ret_ad, ret)
 
 def msvcrt_fprintf(jitter):
     ret_addr, args = jitter.func_args_cdecl(['file', 'fmt'])
     cur_arg, fmt = 2, args.fmt
-    output = get_fmt_args(jitter, fmt, cur_arg, jitter.get_str_ansi)
+    output = get_fmt_args(jitter, fmt, cur_arg, lambda addr:get_win_str_a(jitter, addr))
     ret = len(output)
-    log.info("fprintf(%x, '%s') = '%s'" % (args.file, jitter.get_str_ansi(args.fmt), output))
+    log.info("fprintf(%x, '%s') = '%s'" % (args.file, lambda addr:get_win_str_a(jitter, addr)(args.fmt), output))
 
     fd = jitter.vm.get_u32(args.file + 0x10)
     if not fd in winobjs.handle_pool:
@@ -2099,8 +2104,8 @@ def msvcrt_fprintf(jitter):
 def shlwapi_StrCmpNIA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2",
                                              "nchar"])
-    s1 = jitter.get_str_ansi(args.ptr_str1).lower()
-    s2 = jitter.get_str_ansi(args.ptr_str2).lower()
+    s1 = get_win_str_a(jitter, args.ptr_str1).lower()
+    s2 = get_win_str_a(jitter, args.ptr_str2).lower()
     s1 = s1[:args.nchar]
     s2 = s2[:args.nchar]
     jitter.func_ret_stdcall(ret_ad, cmp(s1, s2))
@@ -2109,7 +2114,7 @@ def shlwapi_StrCmpNIA(jitter):
 def advapi32_RegCreateKeyW(jitter):
     ret_ad, args = jitter.func_args_stdcall(["hkey", "subkey",
                                              "phandle"])
-    s_subkey = jitter.get_str_unic(args.subkey).lower() if args.subkey else ""
+    s_subkey = get_win_str_w(jitter, args.subkey).lower() if args.subkey else ""
 
     ret_hkey = 0
     ret = 2
@@ -2130,7 +2135,7 @@ def kernel32_GetCurrentDirectoryA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["size","buf"])
     dir_ = winobjs.cur_dir
     log.debug("GetCurrentDirectory() = '%s'" % dir_)
-    jitter.vm.set_mem(args.buf, dir_[:args.size-1] + b"\x00")
+    set_win_str_a(jitter, args.buf, dir_[:args.size-1])
     ret = len(dir_)
     if args.size <= len(dir_):
         ret += 1
@@ -2159,11 +2164,11 @@ def advapi32_RegOpenKeyEx(jitter, funcname, get_str):
 
 
 def advapi32_RegOpenKeyExA(jitter):
-    advapi32_RegOpenKeyEx(jitter, whoami(), jitter.get_str_ansi)
+    advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def advapi32_RegOpenKeyExW(jitter):
-    advapi32_RegOpenKeyEx(jitter, whoami(), jitter.get_str_unic)
+    advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def advapi32_RegSetValue(jitter, funcname, get_str):
@@ -2193,19 +2198,19 @@ def advapi32_RegCloseKey(jitter):
     jitter.func_ret_stdcall(ret_ad, 0)
 
 def advapi32_RegSetValueExA(jitter):
-    advapi32_RegSetValueEx(jitter, whoami(), jitter.get_str_ansi)
+    advapi32_RegSetValueEx(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def advapi32_RegSetValueExW(jitter):
-    advapi32_RegOpenKeyEx(jitter, whoami(), jitter.get_str_unic)
+    advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def advapi32_RegSetValueA(jitter):
-    advapi32_RegSetValue(jitter, whoami(), jitter.get_str_ansi)
+    advapi32_RegSetValue(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def advapi32_RegSetValueW(jitter):
-    advapi32_RegSetValue(jitter, whoami(), jitter.get_str_unic)
+    advapi32_RegSetValue(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_GetThreadLocale(jitter):
@@ -2220,15 +2225,15 @@ def kernel32_SetCurrentDirectory(jitter, get_str):
     jitter.func_ret_stdcall(ret_ad, 1)
 
 def kernel32_SetCurrentDirectoryW(jitter):
-    return kernel32_SetCurrentDirectory(jitter, jitter.get_str_unic)
+    return kernel32_SetCurrentDirectory(jitter, lambda addr:get_win_str_w(jitter, addr))
 
 def kernel32_SetCurrentDirectoryA(jitter):
-    return kernel32_SetCurrentDirectory(jitter, jitter.get_str_ansi)
+    return kernel32_SetCurrentDirectory(jitter, lambda addr:get_win_str_a(jitter, addr))
 
 def msvcrt_wcscat(jitter):
     ret_ad, args = jitter.func_args_cdecl(['ptr_str1', 'ptr_str2'])
-    s1 = jitter.get_str_unic(args.ptr_str1)
-    s2 = jitter.get_str_unic(args.ptr_str2)
+    s1 = get_win_str_w(jitter, args.ptr_str1)
+    s2 = get_win_str_w(jitter, args.ptr_str2)
     log.info("strcat('%s','%s')" % (s1,s2))
     jitter.vm.set_mem(args.ptr_str1, (s1 + s2).encode("utf-16le") + "\x00\x00")
     jitter.func_ret_cdecl(ret_ad, args.ptr_str1)
@@ -2253,11 +2258,11 @@ def kernel32_GetLocaleInfo(jitter, funcname, set_str):
 
 
 def kernel32_GetLocaleInfoA(jitter):
-    kernel32_GetLocaleInfo(jitter, whoami(), jitter.set_str_ansi)
+    kernel32_GetLocaleInfo(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetLocaleInfoW(jitter):
-    kernel32_GetLocaleInfo(jitter, whoami(), jitter.set_str_unic)
+    kernel32_GetLocaleInfo(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_TlsAlloc(jitter):
@@ -2306,11 +2311,11 @@ def kernel32_GetStartupInfo(jitter, funcname, set_str):
 
 
 def kernel32_GetStartupInfoA(jitter):
-    kernel32_GetStartupInfo(jitter, whoami(), jitter.set_str_ansi)
+    kernel32_GetStartupInfo(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetStartupInfoW(jitter):
-    kernel32_GetStartupInfo(jitter, whoami(), jitter.set_str_unic)
+    kernel32_GetStartupInfo(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_GetCurrentThreadId(jitter):
@@ -2336,7 +2341,7 @@ def user32_GetSystemMetrics(jitter):
 
 def wsock32_WSAStartup(jitter):
     ret_ad, args = jitter.func_args_stdcall(["version", "pwsadata"])
-    jitter.vm.set_mem(args.pwsadata, "\x01\x01\x02\x02WinSock 2.0\x00")
+    jitter.vm.set_mem(args.pwsadata, b"\x01\x01\x02\x02WinSock 2.0\x00")
     jitter.func_ret_stdcall(ret_ad, 0)
 
 
@@ -2430,11 +2435,11 @@ def kernel32_CreateFileMapping(jitter, funcname, get_str):
 
 
 def kernel32_CreateFileMappingA(jitter):
-    kernel32_CreateFileMapping(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_CreateFileMapping(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_CreateFileMappingW(jitter):
-    kernel32_CreateFileMapping(jitter, whoami(), jitter.get_str_unic)
+    kernel32_CreateFileMapping(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_MapViewOfFile(jitter):
@@ -2501,11 +2506,11 @@ def kernel32_GetDriveType(jitter, funcname, get_str):
 
 
 def kernel32_GetDriveTypeA(jitter):
-    kernel32_GetDriveType(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_GetDriveType(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_GetDriveTypeW(jitter):
-    kernel32_GetDriveType(jitter, whoami(), jitter.get_str_unic)
+    kernel32_GetDriveType(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_GetDiskFreeSpace(jitter, funcname, get_str):
@@ -2522,11 +2527,11 @@ def kernel32_GetDiskFreeSpace(jitter, funcname, get_str):
 
 
 def kernel32_GetDiskFreeSpaceA(jitter):
-    kernel32_GetDiskFreeSpace(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_GetDiskFreeSpace(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_GetDiskFreeSpaceW(jitter):
-    kernel32_GetDiskFreeSpace(jitter, whoami(), jitter.get_str_unic)
+    kernel32_GetDiskFreeSpace(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_VirtualQuery(jitter):
@@ -2574,7 +2579,7 @@ def msvcrt_srand(jitter):
 
 def msvcrt_wcslen(jitter):
     ret_ad, args = jitter.func_args_cdecl(["pwstr"])
-    s = jitter.get_str_unic(args.pwstr)
+    s = get_win_str_w(jitter, args.pwstr)
     jitter.func_ret_cdecl(ret_ad, len(s))
 
 def kernel32_SetFilePointer(jitter):
@@ -2777,8 +2782,8 @@ def user32_MessageBoxA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["hwnd", "lptext",
                                              "lpcaption", "utype"])
 
-    text = jitter.get_str_ansi(args.lptext)
-    caption = jitter.get_str_ansi(args.lpcaption)
+    text = get_win_str_a(jitter, args.lptext)
+    caption = get_win_str_a(jitter, args.lpcaption)
 
     log.info('Caption: %r Text: %r', caption, text)
 
@@ -2794,11 +2799,11 @@ def kernel32_myGetTempPath(jitter, set_str):
 
 
 def kernel32_GetTempPathA(jitter):
-    kernel32_myGetTempPath(jitter, jitter.set_str_ansi)
+    kernel32_myGetTempPath(jitter, lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetTempPathW(jitter):
-    kernel32_myGetTempPath(jitter, jitter.set_str_unic)
+    kernel32_myGetTempPath(jitter, lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 temp_num = 0
@@ -2809,8 +2814,8 @@ def kernel32_GetTempFileNameA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["path", "ext", "unique", "buf"])
 
     temp_num += 1
-    ext = jitter.get_str_ansi(args.ext) if args.ext else 'tmp'
-    path = jitter.get_str_ansi(args.path) if args.path else "xxx"
+    ext = get_win_str_a(jitter, args.ext) if args.ext else 'tmp'
+    path = get_win_str_a(jitter, args.path) if args.path else "xxx"
     fname = path + "\\" + "temp%.4d" % temp_num + "." + ext
     jitter.vm.set_mem(args.buf, fname)
 
@@ -2887,7 +2892,7 @@ class find_data_mngr(object):
 def kernel32_FindFirstFileA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"])
 
-    filepattern = jitter.get_str_ansi(args.pfilepattern)
+    filepattern = get_win_str_a(jitter, args.pfilepattern)
     h = winobjs.find_data.findfirst(filepattern)
 
     fname = winobjs.find_data.findnext(h)
@@ -2951,7 +2956,7 @@ def msvcrt__ultow(jitter):
     if not args.radix in [10, 16, 20]:
         raise ValueError("Not tested")
     s = int2base(value, args.radix)
-    jitter.vm.set_mem(args.p, jitter.set_str_unic(s + "\x00"))
+    jitter.vm.set_mem(args.p, lambda addr,value: set_win_str_w(jitter, addr, value)(s + "\x00"))
     jitter.func_ret_cdecl(ret_ad, args.p)
 
 
@@ -2978,15 +2983,15 @@ def msvcrt_myfopen(jitter, get_str):
 
 
 def msvcrt__wfopen(jitter):
-    msvcrt_myfopen(jitter, jitter.get_str_unic)
+    msvcrt_myfopen(jitter, lambda addr:get_win_str_w(jitter, addr))
 
 
 def msvcrt_fopen(jitter):
-    msvcrt_myfopen(jitter, jitter.get_str_ansi)
+    msvcrt_myfopen(jitter, lambda addr:get_win_str_a(jitter, addr))
 
 
 def msvcrt_strlen(jitter):
     ret_ad, args = jitter.func_args_cdecl(["src"])
 
-    s = jitter.get_str_ansi(args.src)
+    s = get_win_str_a(jitter, args.src)
     jitter.func_ret_cdecl(ret_ad, len(s))
diff --git a/miasm/os_dep/win_api_x86_32_seh.py b/miasm/os_dep/win_api_x86_32_seh.py
index dadd0889..8e485285 100644
--- a/miasm/os_dep/win_api_x86_32_seh.py
+++ b/miasm/os_dep/win_api_x86_32_seh.py
@@ -81,7 +81,7 @@ return_from_exception = 0x6eadbeef
 
 name2module = []
 main_pe = None
-main_pe_name = b"c:\\xxx\\toto.exe"
+main_pe_name = "c:\\xxx\\toto.exe"
 
 MAX_SEH = 5
 
@@ -254,9 +254,9 @@ def create_modules_chain(jitter, name2module):
                         fname)
             continue
         addr = base_addr + i * 0x1000
-        bpath = fname.replace(b'/', b'\\')
+        bpath = fname.replace('/', '\\')
         bname_str = os.path.split(fname)[1].lower()
-        bname_unicode = bname_str.decode('utf8').encode("utf-16le")
+        bname_unicode = bname_str.encode("utf-16le")
         log.info("Add module %x %r", pe_obj.NThdr.ImageBase, bname_str)
 
         modules_info.add(bname_str, pe_obj, addr)
diff --git a/test/arch/x86/qemu/testqemu.py b/test/arch/x86/qemu/testqemu.py
index 594a826b..64312928 100644
--- a/test/arch/x86/qemu/testqemu.py
+++ b/test/arch/x86/qemu/testqemu.py
@@ -48,7 +48,7 @@ def xxx___printf_chk(jitter):
     ret_ad, args = jitter.func_args_systemv(["out", "format"])
     if args.out != 1:
         raise RuntimeError("Not implemented")
-    fmt = jitter.get_str_ansi(args.format)
+    fmt = jitter.get_c_str(args.format)
     # Manage llx
     fmt = fmt.replace("llx", "lx")
     fmt = fmt.replace("%016lx", "%016z")
@@ -60,7 +60,7 @@ def xxx___printf_chk(jitter):
     for x in fmt_a:
         a = jitter.vm.get_u32(esp + 8 + 4*i)
         if x == "s":
-            a = jitter.get_str_ansi(a)
+            a = jitter.get_c_str(a)
         elif x in ("x", 'X', "d"):
             pass
         elif x.lower() in ("f", "l"):
@@ -102,7 +102,7 @@ def xxx_puts(jitter):
     writes the string s and a trailing newline to stdout.
     '''
     ret_addr, args = jitter.func_args_systemv(['target'])
-    output = jitter.get_str_ansi(args.target)
+    output = jitter.get_c_str(args.target)
     # Check with expected result
     line = next(expected)
     if output != line.rstrip():
diff --git a/test/arch/x86/qemu/testqemu64.py b/test/arch/x86/qemu/testqemu64.py
index 636cb6a9..8d25ca68 100644
--- a/test/arch/x86/qemu/testqemu64.py
+++ b/test/arch/x86/qemu/testqemu64.py
@@ -48,7 +48,7 @@ def xxx___printf_chk(jitter):
     ret_ad, args = jitter.func_args_systemv(["out", "format"])
     if args.out != 1:
         raise RuntimeError("Not implemented")
-    fmt = jitter.get_str_ansi(args.format)
+    fmt = jitter.get_c_str(args.format)
     # Manage llx
     fmt = fmt.replace("llx", "lx")
     fmt = fmt.replace("%016lx", "%016z")
@@ -60,7 +60,7 @@ def xxx___printf_chk(jitter):
     for x in fmt_a:
         a = jitter.get_arg_n_systemv(2 + i)
         if x == "s":
-            a = jitter.get_str_ansi(a)
+            a = jitter.get_c_str(a)
         elif x in ("x", 'X', 'd', 'z', 'Z'):
             pass
         elif x.lower() in ("f","l"):
@@ -98,7 +98,7 @@ def xxx_puts(jitter):
     writes the string s and a trailing newline to stdout.
     '''
     ret_addr, args = jitter.func_args_systemv(['target'])
-    output = jitter.get_str_ansi(args.target)
+    output = jitter.get_c_str(args.target)
     # Check with expected result
     line = next(expected)
     if output != line.rstrip():
diff --git a/test/os_dep/linux/stdlib.py b/test/os_dep/linux/stdlib.py
index ef890625..a0432e65 100755
--- a/test/os_dep/linux/stdlib.py
+++ b/test/os_dep/linux/stdlib.py
@@ -33,7 +33,7 @@ class TestLinuxStdlib(unittest.TestCase):
         jit.push_uint32_t(buf)
         jit.push_uint32_t(0) # ret_ad
         stdlib.xxx_sprintf(jit)
-        ret = jit.get_str_ansi(buf)
+        ret = jit.get_c_str(buf)
         self.assertEqual(ret, "'coucou' 1111")
 
 
diff --git a/test/os_dep/win_api_x86_32.py b/test/os_dep/win_api_x86_32.py
index f759c6af..66a4e628 100755
--- a/test/os_dep/win_api_x86_32.py
+++ b/test/os_dep/win_api_x86_32.py
@@ -6,6 +6,7 @@ import unittest
 import logging
 from miasm.analysis.machine import Machine
 import miasm.os_dep.win_api_x86_32 as winapi
+from miasm.os_dep.win_api_x86_32 import get_win_str_a, get_win_str_w
 from miasm.core.utils import pck32
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
 
@@ -42,7 +43,7 @@ class TestWinAPI(unittest.TestCase):
         jit.push_uint32_t(buf)
         jit.push_uint32_t(0) # ret_ad
         winapi.msvcrt_sprintf(jit)
-        ret = jit.get_str_ansi(buf)
+        ret = get_win_str_a(jit, buf)
         self.assertEqual(ret, "'coucou' 1111")
 
 
@@ -63,7 +64,7 @@ class TestWinAPI(unittest.TestCase):
         jit.push_uint32_t(buf)
         jit.push_uint32_t(0) # ret_ad
         winapi.msvcrt_swprintf(jit)
-        ret = jit.get_str_unic(buf)
+        ret = get_win_str_w(jit, buf)
         self.assertEqual(ret, u"'coucou' 1111")
 
 
@@ -94,7 +95,7 @@ class TestWinAPI(unittest.TestCase):
         jit.push_uint32_t(size)   # size
         jit.push_uint32_t(0)      # @return
         winapi.kernel32_GetCurrentDirectoryA(jit)
-        dir_ = jit.get_str_ansi(addr)
+        dir_ = get_win_str_a(jit, addr)
         size_ret = jit.cpu.EAX
         self.assertEqual(len(dir_), size_ret)
 
@@ -106,7 +107,7 @@ class TestWinAPI(unittest.TestCase):
         winapi.kernel32_GetCurrentDirectoryA(jit)
         size_ret = jit.cpu.EAX
         self.assertEqual(len(dir_)+1, size_ret)
-        dir_short = jit.get_str_ansi(addr)
+        dir_short = get_win_str_a(jit, addr)
         self.assertEqual(dir_short, dir_[:4])
 
     def test_MemoryManagementFunctions(self):