101

Re: AHK: Класс для работы с JSON

teadrinker пишет:

Не доверяешь — не запускай. Я постоянно пользуюсь JSON только из Гугл-транслейта, и то его не запускаю, а разбираю парсингом.

Если ты выполняешь eval, то тем самым ты его уже запускаешь.

teadrinker пишет:

За весь свой опыт не помню ситуации, чтобы был риск запустить из JSON вредоносный код. Можешь привести пример таковой?

Я могу привести пример как запустить ActiveXObject из json.
Создастся test.txt на диске D.
В IE нужно разрешить initialize and script Active X controls.

json = {"key": "value"});var fso = new ActiveXObject('Scripting.FileSystemObject');fso.CreateTextFile('D:\\test.txt');({}
doc := ComObjCreate("htmlfile")
doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=EDGE"">")
JS := doc.parentWindow
JS.eval("(" json ")")

Возможно есть варианты написания серьезных эксплойтов, но это надо интересоваться на соответствующих форумах.
Наверное стоит у Xameleon спросить примеры - может он в курсе.

102

Re: AHK: Класс для работы с JSON

Malcev пишет:

Если ты выполняешь eval, то тем самым ты его уже запускаешь

Да, всё правильно. Я почему-то подумал, что там eval нету, но был не прав. Так это как раз тот случай, когда я источнику доверяю на 100%.

Malcev пишет:

Я могу привести пример как запустить ActiveXObject из json.

Так значит имеющегося

JS.("delete ActiveXObject; delete GetObject;")

достаточно?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

103

Re: AHK: Класс для работы с JSON

Вот не знаю, спрошу у Xameleona, какие в принципе могут быть варианты эксплойта.

104 (изменено: teadrinker, 2021-02-10 03:48:24)

Re: AHK: Класс для работы с JSON

Malcev пишет:

Я могу привести пример как запустить ActiveXObject из json.

Собственно, я имел в виду не как запустить код технически, а конкретную ситуацию, когда этот код мог бы у меня появиться.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

105

Re: AHK: Класс для работы с JSON

Malcev пишет:

может просто достаточно удалить объекты из json перед выполнением eval?

Нет, мы там не из json объекты удаляем, а из запускающего его js-объекта.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

106

Re: AHK: Класс для работы с JSON

teadrinker пишет:

Собственно, я имел в виду не как запустить код технически, а конкретную ситуацию, когда этот код мог бы у меня появиться.

Ну, например, сайт с которого получаем json поймал вирус.

teadrinker пишет:

Нет, мы там не из json объекты удаляем, а из запускающего его js-объекта.

А, сейчас поправлю.

107

Re: AHK: Класс для работы с JSON

Malcev пишет:

Ну, например, сайт с которого получаем json поймал вирус.

Да, наверно возможно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

108

Re: AHK: Класс для работы с JSON

Собственно, от eval можно избавиться, вместо

JS.eval("(" . json . ")")

можно использовать

JS.JSON.parse(json)
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

109

Re: AHK: Класс для работы с JSON

Наверное это лучший вариант.

110

Re: AHK: Класс для работы с JSON

Правда тут надо еще будет скорости сравнить.

111

Re: AHK: Класс для работы с JSON

Сравнил, примерно одинаково, с parse чуть быстрее:

#NoEnv
SetBatchLines, -1

url := "https://addons-ecs.forgesvc.net/api/v2/addon/8025/files"

whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.Open("GET", url, false)
whr.Send()
arr := whr.responseBody
pData := NumGet(ComObjValue(arr) + 8 + A_PtrSize)
MsgBox, % "json size: " . (length := arr.MaxIndex() + 1)//1024 . " kB"
MsgBox, % json := StrGet(pData, length, "utf-8")

for k, v in ["parse", "eval"] {
   start := A_TickCount
   Obj_%v% := JsonToAHK_%v%(json)
   time_%v% := A_TickCount - start
}
MsgBox, % "parse: " . time_parse . "`neval: " . time_eval

JsonToAHK_parse(json, rec := false) {
   static doc := ComObjCreate("htmlfile")
         , __ := doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
         , JS := doc.parentWindow
   if !rec
      obj := %A_ThisFunc%(JS.JSON.parse(json), true)
   else if !IsObject(json)
      obj := json
   else if JS.Object.prototype.toString.call(json) == "[object Array]" {
      obj := []
      Loop % json.length
         obj.Push( %A_ThisFunc%(json[A_Index - 1], true) )
   }
   else {
      obj := {}
      keys := JS.Object.keys(json)
      Loop % keys.length {
         k := keys[A_Index - 1]
         obj[k] := %A_ThisFunc%(json[k], true)
      }
   }
   Return obj
}

JsonToAHK_eval(json, rec := false) {
   static doc := ComObjCreate("htmlfile")
         , __ := doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
         , JS := doc.parentWindow
   if !rec
      obj := %A_ThisFunc%(JS.eval("(" . json . ")"), true)
   else if !IsObject(json)
      obj := json
   else if JS.Object.prototype.toString.call(json) == "[object Array]" {
      obj := []
      Loop % json.length
         obj.Push( %A_ThisFunc%(json[A_Index - 1], true) )
   }
   else {
      obj := {}
      keys := JS.Object.keys(json)
      Loop % keys.length {
         k := keys[A_Index - 1]
         obj[k] := %A_ThisFunc%(json[k], true)
      }
   }
   Return obj
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

112

Re: AHK: Класс для работы с JSON

teadrinker Добрый день. Подскажите, пож-та, хочу вытащить "documentId", но работает если только удалить скобки "[]"


jsonStr = {"response":{"pageSize":20,"docs":[{"id":"ISOGD_7815feb6-1831-4b3b-b643-eb565c8152c3","type":"ISOGD","documentId":"7815feb6-1831-4b3b-b643-eb565c8152c3","reestr":"8150","documentType":"PKR","documentDate":"22.04.2021","documentNumber":"21/00904","areaNames":["ЦАО"],"districtNames":["Хамовники"],"objectAddress":"Пречистенка ул., д.14/1, стр.2","objectName":"Учрежденческое здание","documentName":"Паспорт колористического решения","registrationNumber":"45383000-08-369569","registrationDate":"22.04.2021","cadastralNumbers":["77:01:0001049:1008"],"documentStatusCode":"ACTIVE","documentRegistrationCode":"REGISTERED","organizationName":"ГОСУДАРСТВЕННОЕ ","organizationRoleCode":"ZAK","insertedDate":"22.04.2021 10:57:28","operatorFio":"Смирнов Александр Алексеевич","documentSource":"2","documentOrganizationCode":"MKA","alfFolderId":"0ed711a0-ed93-41b7-8978-8048ca2c0972","registeredFIO":"Пархомик Андрей Валерьевич","updatedDate":"23.04.2021 17:09:27","title":"№ 21/00904  от 22.04.2021 Пречистенка ул., д.14/1, стр.2 (ЦАО, Хамовники)"}]},"highlighting":{"map":{"ISOGD_7815feb6-1831-4b3b-b643-eb565c8152c3":{"cadastralNumbers":["<b>77:01:0001049:1008</b>"]}}}}

obj := JSON.Parse(jsonStr)
MsgBox, % obj.response.docs.documentId
return

	

 
class JSON
{
   static JS := JSON._GetJScripObject()
   
   Parse(JsonString)  {
      try oJSON := this.JS.("(" JsonString ")")
      catch  {
         MsgBox, Wrong JsonString!
         Return
      }
      Return this._CreateObject(oJSON)
   }
   
   Stringify(obj)  {
      if IsObject( obj )  {
         isArray := true
         for key in obj
            if !( key = A_Index || isArray := false )
               break
            
         for k, v in obj
            str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : this.Stringify(k) . ":" ) . this.Stringify(v)

         return isArray ? "[" str "]" : "{" str "}"
      }
      else if !(obj*1 = "" || RegExMatch(obj, "\s"))
         return obj
      
      for k, v in [["\", "\\"], [A_Tab, "\t"], ["""", "\"""], ["/", "\/"], ["`n", "\n"], ["`r", "\r"], [Chr(12), "\f"], [Chr(08), "\b"]]
         obj := StrReplace( obj, v[1], v[2] )
      
      while RegexMatch( obj, "[^\x20-\x7e]", key )  {
         str := Asc( key )
         val := "\u" . Chr( ( ( str >> 12 ) & 15 ) + ( ( ( str >> 12 ) & 15 ) < 10 ? 48 : 55 ) )
               . Chr( ( ( str >> 8 ) & 15 ) + ( ( ( str >> 8 ) & 15 ) < 10 ? 48 : 55 ) )
               . Chr( ( ( str >> 4 ) & 15 ) + ( ( ( str >> 4 ) & 15 ) < 10 ? 48 : 55 ) )
               . Chr( ( str & 15 ) + ( ( str & 15 ) < 10 ? 48 : 55 ) )
         obj := StrReplace(obj, key, val)
      }
      Return """" obj """"
   }
   
   GetFromUrl(url, contentType := "", userAgent := "", body := "")  {
      ; в случае удачи будет возвращена JSON-строка, в случае ошибки — массив с одним элементом-строкой с описанием ошибки
      try  {
         XmlHttp := ComObjCreate("Microsoft.XmlHttp")
         XmlHttp.Open("GET", url, false)
         ( contentType && XmlHttp.SetRequestHeader("Content-Type", contentType) )
         ( userAgent && XmlHttp.SetRequestHeader("User-Agent", userAgent) )
         XmlHttp.Send(body)
      }
      catch e
         Return ["Error!`n" . e.Message]
      status := XmlHttp.Status
      Return status = 200 ? XmlHttp.ResponseText : ["Error! Status: " . status . ", ResponseText: " . XmlHttp.ResponseText]
   }

   _GetJScripObject()  {
      VarSetCapacity(tmpFile, ((MAX_PATH := 260) - 14) << !!A_IsUnicode, 0)
      DllCall("GetTempFileName", Str, A_Temp, Str, "AHK", UInt, 0, Str, tmpFile)
      
      FileAppend,
      (
      <component>
      <public><method name='eval'/></public>
      <script language='JScript'></script>
      </component>
      ), % tmpFile
      
      JS := ObjBindMethod( ComObjGet("script:" . tmpFile), "eval" )
      FileDelete, % tmpFile
      JSON._AddMethods(JS)
      Return JS
   }

   _AddMethods(ByRef JS)  {
      JScript =
      (
         Object.prototype.GetKeys = function () {
            var keys = []
            for (var k in this)
               if (this.hasOwnProperty(k))
                  keys.push(k)
            return keys
         }
         Object.prototype.IsArray = function () {
            var toStandardString = {}.toString
            return toStandardString.call(this) == '[object Array]'
         }
      )
      JS.("delete ActiveXObject; delete GetObject;")
      JS.(JScript)
   }

   _CreateObject(ObjJS)  {
      res := ObjJS.IsArray()
      if (res = "")
         Return ObjJS
      
      else if (res = -1)  {
         obj := []
         Loop % ObjJS.length
            obj[A_Index] := this._CreateObject(ObjJS[A_Index - 1])
      }
      else if (res = 0)  {
         obj := {}
         keys := ObjJS.GetKeys()
         Loop % keys.length
            k := keys[A_Index - 1], obj[k] := this._CreateObject(ObjJS[k])
      }
      Return obj
   }
}

)


113

Re: AHK: Класс для работы с JSON

А как вытащить test из такого объекта

Obj := ["test"]

?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

114

Re: AHK: Класс для работы с JSON

teadrinker

Cпасибо!

MsgBox, % obj.response.docs[1].documentId

115

Re: AHK: Класс для работы с JSON

teadrinker А как узнать количество файлов? В данном примере 3 ("obj.files.length" не работает)


FileURL := ""

HTTP.ResponseText = 
{"folderId":"bf6530be-cf29-438b-82c0-a4546a0466ef","folderName":"45383000-08-369567","files":[{"fileId":"91b2a1ba-1a6e-43ba-866b-c7cd491055fc","fileName":"COLOURPASS.xml","fileDate":"2021-04-22T11:00:45.82","contentType":"application/xml","contentLength":5133,"signed":false},{"fileId":"ef07f2af-b165-4a0f-80ef-cb29d4248d03","fileName":"Паспорт колористического решения_ЦАО, Хамовники, Пречистенка ул., д. 14_1, с. 3_21_00905.pdf","fileDate":"2021-04-22T11:00:51.723","contentType":"application/pdf","contentLength":12964301,"signed":false},{"fileId":"86a028fe-2e63-4f27-9ff8-46e9414b1a98","fileName":"Протокол регистрации 369567.xml","fileDate":"2021-04-22T12:27:19.237","contentType":"application/xml","contentLength":459,"signed":false}],"hidden":false}

obj := JSON.Parse(HTTP.ResponseText)

loop 3 
{
  if InStr(obj.files[A_index].fileName, "COLOURPASS")
     UrlDownloadToFile, % FileURL "/" obj.files[A_index].fileId, % "C:\Отчёт\" obj.files[A_index].fileName
  if InStr(obj.files[A_index].fileName, "Паспорт")
    UrlDownloadToFile, % FileURL "/" obj.files[A_index].fileId, % "C:\Отчёт\" obj.files[A_index].fileName
}

116

Re: AHK: Класс для работы с JSON

Не вижу, как эти вопросы связаны с JSON. Преобразование JSON в AHK-объект ведь проблем не вызывает? А если объект уже создан, то без разницы, каким образом он был получен, он поддерживает те же свойства и методы, что и любой обычный AHK-объект. Поэтому, я бы начал с того, что заглянул бы в справку по свойствам и методам объектов, там бы узнал правильный синтаксис.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder