JS逆向之艺恩数据_艺恩逆向-程序员宅基地

技术标签: 爬虫  python  js逆向  javascript  

文章内容仅用于学习和技术交流,如有侵权请联系我删除。

目标网站

https://www.endata.com.cn/BoxOffice/BO/Year/index.html

数据加密问题

我们先看一下返回的加密数据长啥样:
在这里插入图片描述
我们正常对这个接口发请求也能很轻松的拿到这一坨加密数据:

import requests

headers = {
    
    'Connection': 'keep-alive',
    'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"',
    'Accept': 'text/plain, */*; q=0.01',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'X-Requested-With': 'XMLHttpRequest',
    'sec-ch-ua-mobile': '?0',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36',
    'sec-ch-ua-platform': '"Windows"',
    'Origin': 'https://www.endata.com.cn',
    'Sec-Fetch-Site': 'same-origin',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Dest': 'empty',
    'Accept-Language': 'zh-CN,zh;q=0.9',
}

data = {
    
    'year': '2022',
    'MethodName': 'BoxOffice_GetYearInfoData',
}

response = requests.post('https://www.endata.com.cn/API/GetData.ashx', headers=headers, data=data)
print(response.text)

# 6A1E2894667A88450E843A710BA610C931FE552A384B8CE5AD158DFCF37C157518B0DD6EB26151CA687DA5BDEC95862545A3E79A118D05AE1174D1CFDFD7A8766D72B84B607412EB91484FA088AF81C3A3E21F1D96448FB0B3F9EDA1846BCA4103783DCB218C0CB24C2E76B3A8DBC499FF8B3F09D1231570F22340C871C635C504605860D546994D2F1CC63970DDE501BB1A2A8ED55C01AB5EB5B99258BAFFF47CB47DC6083537625D97BBA839265588F89115342D4DA68190F2D5A248AF3350588676696CBB13815BF1EC967CAD53C9D670CFDEEDB4129556C2E69C9EB19769B08E58F3C78C1432B8ADE23EC6173CDA52854B292A7108D2D150D7D63D18FA331D465423F3DBFBE387367B56ED6E15E4041302939B52775F6519675278A589C88B788164B8195499B03E19AD741AC71682E84EEED174FBF2BEB604AA7EF7161022EBB04396C00DE0D350890970B10869332C2EA0F92822C9C4BDC58DAF6E968F60D5E9C8152608DFA39BAD15A5ACB01697DF4BDD1E0FF73E66CCE9CF6B484D50B1A6E23A6D2574FB4886E7FE3DB1F9EBD0A9802F0CD48D6C7E0F8AA11C4DF723F79B4C0E33BA12165C6762648C8E4CCA0D50862F9C6F5C5DB92502E2EEBE0A8E5A798CDD8D95930388FD8520D413FA1F3ACED9CDA4641B10F24DDED87BF3561D751A08175E04ECBFEA23335673408D91BA25414EAAA7DA975F9B73D421D8FF41FCC55FAF9B692B118532428E0F0035867567B0E97C1AF46FD3CF31033DFBCA5E9BF38DE3229BD9FF30285B8E1AD6D4D0E35B2987323BA41E42E65945F9AD92F7F24F66A4CD35A09A93D980C7576274C9655091E81527A6AF63519F56D68E38546FB81F48CB7E0A8D8181CDD74AC932E6A4A6D30A0C4524D105D3EA16C8AA6BA4EF84A097C6D3E8C71764B829A11E784CAEDC79D5B842E9DD88896C2BCC38F9F35558850282971C954A91EBE3458D479CADEC96E70EB023D470484D0AF21CECFB2D724C5409175635E3D75E22FA6EF31EE5A0E000E1FDE7E5192E664DA5BD35AEA2F6F64B2F674C99B09AAB360E418C2E1AAF1A851A53AA50593DC7246EC4439E25E60A16CD47E9B5C09EBA71A91E0EFD10621EED494127792241064F2A72EDE2F07BA1A15380A1A9E433FC8F514145F826FE50845977B143365C4FA4699F5170124C8F3ED8ACD40DE45038F1597BB40F3CD71C5BDB2B1CD0B772823613B0B581FB35FA2DE28049D62CDB59D1336A0FD18A310996F323C66D0F3FBB98D658D8356721B493FE770C1D755D64331D3C20F5FF5255DACC97E784A541D70B08D348C857D5161328E4BD53C92F2826563148F623539F16277FD0DBC1761B6BF86A4C86215A7B6D275D80D85EBD870F54CA8CE2A72C5C918A6D170D38333559F244B8962433310DCDDA1B2987CC8C2EB6C24B3125AB248F4F06CCF1C8D64D9193942FFFA0EEB79FD66017B5114760E86C271804B5A4683C19AD85CED221F6424A2D4E84C416A966522AA980DF4C4D32A7E2386866D09F539A79AFD6C7E8001C4F044EC3B2E68D77C09BEE876E3EDAD6748C5DD63BA520526C95862545A3E79A12AFF5B5874D87754FD7A8766D72B84B6F734089E8CEE7E669A67E562A80BEC91CDD3200088931040EDF81FE6BDF9066818C0CB24C2E76B3A23E9DAE0CC1AAED91231570F22340C875C084DAF56F0E7BE17B74847A7FDF3EA3DBBFC95D1551EE2C5BA480FA193273BBCC067341C911CA475D80D85EBD870F54CA8CE2A72C5C918A6D170D38333559F244B8962433310DC46D9B1CC7F194DCC5706A49952DCD5C5F06CCF1C8D64D9193942FFFA0EEB79FD66017B5114760E86C271804B5A4683C19AD85CED221F6424A2D4E84C416A966522AA980DF4C4D32A7E2386866D09F539D5F8197217CA05BB1D05DB6C129DA99E9F7D073D6F959A8448C5DD63BA520526C95862545A3E79A12974D5D21475A477FD7A8766D72B84B6E21D43E0A1DC60F81B68BEE3232BCFE83D8518A2A817F314E2A13310B3BB03834DCA2C24546334C99502589B4A3C2048342BEED61E88D501C38F9F3555885028546B5429A68E972C58D479CADEC96E70086D8F034DB90689E96AE087E49D6EDEC22498622A9A065708977AB2347FCDC172002B525346688F77F04B3F3B74E275B914EAA7AC05A9B8320B9FD48E1458FDB9FB3F14C60D80AFC68CBB26CBC3EB05368F0ACD62D2AC928FD4DE7ED2B54AE086EC5F30F44BE9ECA14D50371C951A2F322C7A871852D13482481A73419F621477197CD4BFFF08E88E247A13AE2039E191A59D671CF714C0F867E75FFF09839B8304874946CF711B3000FBA1E2B6E99B8E506F4698F6AECF5ACB01697DF4BDD1E0FF73E66CCE9CF6C796362754A5F2B1D2574FB4886E7FE32984582F9DBB02A18C17615434BC9CB3FB860DAF2FA08EA09F3B6AE0062FCFE5B911E82E09B7F44A3A5D3040DDA78E0B731FDCB179B2D3A0DDE170B781DED449FA60E09FBAB852CFEF8AE04A621D7FD2D32DB19C27043F24EA577C9AFD194F28AE02E1C453592CFA2A9607E4C5B745F2C404E9B3E27208632D75230AC8C16F6D9E1A832777EED66E4CCE3372968ED6712F772F24E2E05DFDE06789FAE99168A96D181C9F83DD8F0A3BEC54077A25D67FF580E7304FE9EF3DFB86777E466F786033D3368183E36C5944B15F0DC23631505A12BB00731E88BADC10CA7B3C6CC42CF4EBF6520BF0C5DE643FFC4A3BC80C0B3DE2B1040BBCEB9F294A7EECDC099A098A9A55B92888FB453D8964D84F41BBC59A17EA725C246A427162F42D82993145E7DA8D3E126749D86267A6F0E3BC233D0FD4B2B9CB0548FE9265588F891153429D856FF1B105CBA539D45E8E2A25459CD95930388FD8520D413FA1F3ACED9CDAD1460B030606C44915C975DCBF180C05E04ECBFEA23335673408D91BA25414EAAA7DA975F9B73D421D8FF41FCC55FAF9B692B118532428E0F0035867567B0E97895D5B38C6B87D899067B26A2735F88FC5D13461D6F5BB84EA615638B59FC8B57A5C301CBB29CB139AD92F7F24F66A4CD35A09A93D980C75501A0EDD956DC1C5527A6AF63519F56D8103A5D6B1DD5A7F38A4A571EE07D940ED09A9B7C00669440B13E22EEEFCE76DAE439AD41972DDAF4B54667F59A73199FAFA4CAB3B968A6BAE8B2A9530D07A860DDE501BB1A2A8ED69DE248A451A4BC2AE81F92D5B07F6A192351EAE4B34C38675F30BB3FB7911BDAA96EAF50B16173AF972EF50216E8B4E58543B0E1D942DA875606B1C3B760BFC9326409C9077554ED1CEEB4702CAB9D99D3F94591771BAB3E6279FFD7659AF34AE48F8842244D62F2913343BDF69BB244122DE8C31629509967F58A0F1514D2E592C5C85937FED8410587B60A2DEFCAD9218C2A240369F7C33A402DB35912F39EED00F14519661ED0DAABF01F601D4760146A16A06F931BCCCF3665BE6E3EE1AFC8CD6B2BE5CE8F0C4524D105D3EA16C8AA6BA4EF84A097C6D3E8C71764B829A11E784CAEDC79D5BE6DD515401239B4078B2ABB701C3F6FE850349F90FC78CECB045AB9BC6950D3BDA2474C6B3C61DC4579F8DD86DCFD8E3874A9B50E07F7E903CE9A02E89690F3D1F5BB8C47CE3DA0EB06F2982C70FCB757780FE8A963D05D9865A5D8E797CFFAED0C25C4EC01940754E5F7AD313BEB34DB5EF2620DF3D5C737024BC1C63B74DE7909D39F1BF70A84738D28C06D6B78C7CEFE885A8CAD27019EC0BE6F9C7EA59CD245554B0AB8E6F167B1927AC474B2F0E66742F4558DD332FBB78AFE064C3346D9EB2D00D38B2000B867CC2CDB1B76A8300FB4894473C1DEEF2E29351738F5EB03DE2B1040BBCEB9FB7F5CEE24EEC2E27980041059D35701D3D8964D84F41BBC51925E69F6A6C666D7162F42D829931450DD99096C42E715E6267A6F0E3BC233DD325A0B1A295CD379C02010C9629FD58D4DA68190F2D5A248AF3350588676696CBB13815BF1EC9677BC7B7EB923B3A88DB4129556C2E69C9EB19769B08E58F3C78C1432B8ADE23EC6173CDA52854B292A7108D2D150D7D6305EA5D638F835AB122D5BD16C768230F80FD803A2D570AB3D55D148F1E0859D30E5382CE428A1D5703A43B26633571B0BAFB18D708E3D1F2174FBF2BEB604AA78B2E56ECBC4DD6A577A89AF4D3876EDBF324C7D2C3B30F73C5DB1F0EEF60E8E29DD573A3BCF2D85AEFB47AA02DF309AA570C85B510D1D75F3D8518A2A817F314EB829431D276076333359D9B876A9C169502589B4A3C20484C57161CEED4B5FEC38F9F35558850285A867C556D5C4D1158D479CADEC96E7069BE235104AFDE1A832B85AD5950A8298D78FF454DDEFB6908977AB2347FCDC172002B525346688F900155F39ECB1DA0B914EAA7AC05A9B8320B9FD48E1458FDB9FB3F14C60D80AFC68CBB26CBC3EB05368F0ACD62D2AC928FD4DE7ED2B54AE0341495C35882FFAC14910E93A1125325D1819AF869A3F0B1E8F231E8ABCAFF2AE530A307F2439C7BB31F1CE202850D8891A59D671CF714C0F4B11CD526CD3D6106EF3394A2AA5C3F3000FBA1E2B6E99B823371420E2F639C7E71586671541A932D3BB265C62BFD8C3D8518A2A817F314E2A13310B3BB03834DCA2C24546334C99502589B4A3C2048CC6E5F4DC6EFF100C38F9F3555885028F25F34526C30F1E158D479CADEC96E70B3A9485848411E7821CECFB2D724C5409175635E3D75E22FA6EF31EE5A0E000E1FDE7E5192E664DAC26A6005CEF9F7EDF674C99B09AAB360E418C2E1AAF1A851A53AA50593DC7246EC4439E25E60A16CD47E9B5C09EBA71A91E0EFD10621EED494127792241064F2DCB59FBC006601598982BC7071245DDAB0F5D4B1BF8E8AD7DD16195A64E5EF74A712523AAA3E1E028ACD40DE45038F15AA08B6E8342635D3D51A6805C9B418CF3B0B581FB35FA2DED8E86028DC3554BC468EC7185D253FCEFF3189D245B63715B892DFB0F9A7579FC4524D105D3EA16CFC33072D1B73D60A6D3E8C71764B829A11E784CAEDC79D5B9544373AE4C100B778B2ABB701C3F6FE082DAC43E9EB0175B045AB9BC6950D3B8A490CEFFD3ACBA3579F8DD86DCFD8E3874A9B50E07F7E903CE9A02E89690F3D3F9DB6984D6B1B9FA6336CC99E1CF53B7780FE8A963D05D9865A5D8E797CFFAED0C25C4EC01940754E5F7AD313BEB34DB5EF2620DF3D5C737024BC1C63B74DE75547EF04151DEBBF8B5488E8506291DB57B7DB0A0E3DD457F48080A9629A9DE1343974396B4EB3D3EB62BDBD381A812466742F4558DD332FB3A998C67C46420C1D66C2462AAECDA8867CC2CDB1B76A83ABA0AED0476964B429AA0E5FE03322903DE2B1040BBCEB9F294A7EECDC099A098A9A55B92888FB453D8964D84F41BBC5111DF4F99358893A7162F42D829931456DF53FFCA9A96A1B6267A6F0E3BC233D9DF2B98CA0E8C88E9C02010C9629FD58D4DA68190F2D5A248AF3350588676696CBB13815BF1EC967D14658EAC300459EDB4129556C2E69C9EB19769B08E58F3C78C1432B8ADE23EC6173CDA52854B292A7108D2D150D7D63D18FA331D465423FAB4F045454AFB2E140EB6BCCB9E7A95FF0B74AB89CAE7BCA486281D1CF3A05D29F2134C165BC266D41AC71682E84EEED174FBF2BEB604AA79CDA1795112CB5B733D8C401CD34FCE1F33BC206B07BDD89037A3D951DF73BC1D44C9E3CC68C82D5F2CA04BF711CE8F5013EBC298D43AC3DF61FD6AB815BD6010B13E22EEEFCE76DE2AC1890D10888134FE5A938C9D8387026858C6E3ADC19F42F59F6B93C7A259B0DDE501BB1A2A8ED372CB8FE722E2E3DCA72DBD630725D1583537625D97BBA839265588F89115342D4DA68190F2D5A248AF3350588676696CBB13815BF1EC967CAD53C9D670CFDEEDB4129556C2E69C9EB19769B08E58F3C78C1432B8ADE23EC6173CDA52854B292A7108D2D150D7D63D18FA331D465423F96CA6A45E7E2766F6A515B454F5638D1962DE99613BAA017820FF446068A11B988EF86025E7764946B5960F60272EA67174FBF2BEB604AA729CDA8E387447ADAE5F424620CEFFFD38E62FEAECA8AC694078EE736B4E58016B05F154BA7E118120B13E22EEEFCE76DDDFB7CBE324CD7144FE5A938C9D8387026858C6E3ADC19F48D326D138F8931780DDE501BB1A2A8EDB08D990A410AED4D1A2B28C30CE02DB292351EAE4B34C3860F14B4965CF3E0B5AA96EAF50B16173AF972EF50216E8B4E58543B0E1D942DA846E12CAB8035DD169326409C9077554ED1CEEB4702CAB9D99D3F94591771BAB3E6279FFD7659AF34AE48F8842244D62F2913343BDF69BB2407570465F75008CFEA7AFCD80F64056446F7A37DBADB1549457F0D9BFCD93D2502B1E90EE4F46B9E33A402DB35912F39EED00F14519661ED950FBC0F902792150146A16A06F931BCC0D9BC9E71ED55AA2C0294367AE26FAA87D24E7FA23584157226E15FFB5518533D8518A2A817F314E2A13310B3BB03834DCA2C24546334C99502589B4A3C2048B8400EDCF985CC5FC38F9F3555885028E46061D59F1F5BDB58D479CADEC96E7078ADFFDDEAE3A95FE96AE087E49D6EDEC22498622A9A065708977AB2347FCDC172002B525346688F53DDEE99579AD35CB914EAA7AC05A9B8320B9FD48E1458FDB9FB3F14C60D80AFC68CBB26CBC3EB05368F0ACD62D2AC928FD4DE7ED2B54AE0341495C35882FFAC6FAE98FFEFD208059A5F8D3BB7742E9444F12F2FD7426079B34660AE6BA2318419841F4B09086F6291A59D671CF714C079D3014D456B86A72B2B476F6B329C1F3000FBA1E2B6E99B6EBFBE084D8FA908FFEF315D7DA1CE8BC4524D105D3EA16C5E65D0FB8D0171C91A14DAF3BABFCEF011E784CAEDC79D5BEFE980DA5BFBDFEA78B2ABB701C3F6FE082DAC43E9EB0175B045AB9BC6950D3B8A490CEFFD3ACBA3579F8DD86DCFD8E3874A9B50E07F7E903CE9A02E89690F3D3F9DB6984D6B1B9FAC4D375CE7BC3F147780FE8A963D05D9865A5D8E797CFFAED0C25C4EC01940754E5F7AD313BEB34DB5EF2620DF3D5C737024BC1C63B74DE75547EF04151DEBBF544BABF51422D07DA0B185B9E57F16A4651C00974EFE72BE4BDFC3380E397B073829FF34FA20DFEB66742F4558DD332F446DF08D401E894CF964ADFBDBE24C01867CC2CDB1B76A8346624A012AAEB5ADB13D99E20B789BD13DE2B1040BBCEB9F294A7EECDC099A098A9A55B92888FB453D8964D84F41BBC553E1B38282932DBB7162F42D829931459060D1561A3912DE6267A6F0E3BC233D84CC4AA11B955D6D9C02010C9629FD58D4DA68190F2D5A248AF3350588676696CBB13815BF1EC967F2C6CC2E93072A9FDB4129556C2E69C9EB19769B08E58F3C78C1432B8ADE23EC6173CDA52854B292A7108D2D150D7D63D18FA331D465423FAB4F045454AFB2E1A11671E04A97DE1DC437A6E03C777958D6EDFE17C880DCAF28CBCB618AA83EC5859F48EEACC97885174FBF2BEB604AA7DCD42BCB362360E933D8C401CD34FCE1F324C7D2C3B30F7326CCD24470EEEB983E5D8DA362716A8F0B13E22EEEFCE76D585462A4F2BE49A7D888DDAB3464547F26858C6E3ADC19F4B272FA6BD8F613910DDE501BB1A2A8ED7E73D504AA99862A5F680A529799586192351EAE4B34C38675F30BB3FB7911BDAA96EAF50B16173AF972EF50216E8B4EFB8D727081218081E185B70E8497B1909326409C9077554ED1CEEB4702CAB9D99D3F94591771BAB3E6279FFD7659AF34AE48F8842244D62F2913343BDF69BB24A6FD19F33AB7FED2E1197B2DD04813C35505301EABFDA911A1E97591D0B451F04BF47428F4D7F3E633A402DB35912F39EED00F14519661ED211354391E575D920146A16A06F931BC9736DB1F978B92361EFC24ECE8F3D9C8FD980288626E917E1799BAECDF708AF6539E553AF3557790E770C1D755D643312C65E99A090F16BCC97E784A541D70B077D65ED1A37B807FDD75AC4EC172DFEC8DC2C95224000C4577FD0DBC1761B6BFBF074A6CA5383E58C6F5C5DB92502E2EEBE0A8E5A798CDD8D95930388FD8520D413FA1F3ACED9CDA4641B10F24DDED8739913B1118459DB4E04ECBFEA23335673408D91BA25414EAAA7DA975F9B73D421D8FF41FCC55FAF9B692B118532428E0F0035867567B0E97990B340D65B96AEA17DFDF511968C719DBBACAACA4AB28B9C007E148719AC080C32E12A67008FB019AD92F7F24F66A4CD35A09A93D980C75C15965FD34C4DA34527A6AF63519F56D6C8A9D8C29743BB00C61DA1A472CB1D89540E157DD659ABC3CF46F5F689F7F85948A337AA06AC4E80B13E22EEEFCE76DE2AC1890D10888134FE5A938C9D8387026858C6E3ADC19F4DE0E89FEBCD3F99C0DDE501BB1A2A8ED8EC73AC58992F2F8BBE60859DC5559FB92351EAE4B34C3860F14B4965CF3E0B5AA96EAF50B16173AF972EF50216E8B4E58543B0E1D942DA8565CC233F7AF6D7B9326409C9077554ED1CEEB4702CAB9D99D3F94591771BAB3E6279FFD7659AF34AE48F8842244D62F556DA5D2FE303D5047A9EAF20FD10DA27E3AA9FBE5312F6038EFCCD4E212CC9046854E4073FBA70A66B4C998AAC0EA3433A402DB35912F39EED00F14519661ED776FECB69621276E0146A16A06F931BC63F7CB34BB29D11AAED9B3C6791D017E337A444FF9C55FF723A0ABF3BE3B49BA035D6514F6695345BE5B597B39D1CFB13B010417CD87E6B33C015577C709C64C8C17615434BC9CB353FA9F01AE72814F9F3B6AE0062FCFE5D4AC691FBFF35B3FD018B5E8E8043BB81E25D879BCDB5834A6EF31EE5A0E000E1FDE7E5192E664DA22420FD21B29AD49F674C99B09AAB360E418C2E1AAF1A851A53AA50593DC7246EC4439E25E60A16CD47E9B5C09EBA71A91E0EFD10621EED4311BD85F74CE88F53D23DB56D19E59D7C91D29C7AC7E6A29E4FA905FA57A736C5645194EB45218B923CED0DAC81C1AB08ACD40DE45038F151F592EF4673B8CF6F182B27585B84CCA3B0B581FB35FA2DE2B0EC9834C0C74E9AA1CC20114CC85263A43ED37FB54A06D9AF21ED7DA2109A6C4524D105D3EA16C5E65D0FB8D0171C91A14DAF3BABFCEF011E784CAEDC79D5B0F5FDE2CA756875D7162F42D829931456DF53FFCA9A96A1B6267A6F0E3BC233D84CC4AA11B955D6D9C02010C9629FD58D4DA68190F2D5A248AF3350588676696CBB13815BF1EC96799B4AE32B0877A7DDB4129556C2E69C9EB19769B08E58F3C78C1432B8ADE23EC6173CDA52854B292A7108D2D150D7D63D18FA331D465423F96CA6A45E7E2766F5D3BDA797378FA4B1FC816F7E5D6212FB4786B838F1D2554C31B939311676C0B939B84AACA4FE01D94C0547CACD01FA52D96A4C2D9252A5A8699F8FCB6A5F9CA

分析接口,断点调试

问题的关键就是咱们怎么解密,我们直接跟栈看一下,它必定会发ajax请求
在这里插入图片描述
点进去
在这里插入图片描述
打个断点调试一下看看,不出意外应该就是else里面对数据解密
在这里插入图片描述
继续往下走一步
在这里插入图片描述
果然数据过了else,已经解密出来了,在此我们就可以断定webInstace.shell(data)是对数据进行解密的。

我们直接进入这个方法里面:
在这里插入图片描述
到这里可能看着一脸懵逼,觉得无从下手,不要懵,继续分析逻辑,哪个变量不认识直接在控制台输出一下看看,就像这样
在这里插入图片描述
_0x2246(‘0x257’, ‘nArV’)这个东西运算出来的最终结果也就是一个shell字符串,我们知道在js里面,
this[‘shell’] 和 this.shell是一样的,所以第2173行就是this.shell = function(_0xa0c834),

所有这个this.shell就是我们之前见到的webInstace.shell,我们可以在这个js文件里面搜一下webInstace,在这里插入图片描述

可以看到在最后一行创建的这个对象,我们再搜一下webDES
在这里插入图片描述

发现最后还是到了这里。

简化还原 js

所以我们可以在这里直接把webDES全部抠出来,慢慢分析

var webDES = function() {
    
    var _0x4da59e = {
    
        'bUIIa': function _0x2a2af9(_0x779387, _0x4a4fec) {
    
            return _0x779387 + _0x4a4fec;
        }
    };
    var _0x9843d3 = function(_0x29d556, _0xcc6df, _0x3d7020) {
    
        if (0x0 == _0xcc6df)
            return _0x29d556[_0x2246('0x254', '4VZ$')](_0x3d7020);
        var _0x48914b;
        _0x48914b = '' + _0x29d556[_0x2246('0x255', 'GL3Q')](0x0, _0xcc6df);
        return _0x48914b += _0x29d556['substr'](_0x4da59e[_0x2246('0x256', 'DK[&')](_0xcc6df, _0x3d7020));
    };
    this[_0x2246('0x257', 'nArV')] = function(_0xa0c834) {
    
        var _0x51eedc = {
    
            'pKENi': function _0x2f627(_0x5b6f5a, _0x440924) {
    
                return _0x5b6f5a === _0x440924;
            },
            'wnfPa': 'ZGz',
            'VMmle': '7|1|8|9|5|2|3|6|0|4',
            'GKWFf': function _0x1a4e13(_0x40cfde, _0x16f3c2) {
    
                return _0x40cfde == _0x16f3c2;
            },
            'MUPgQ': function _0x342f0d(_0x19038b, _0x4004d6) {
    
                return _0x19038b >= _0x4004d6;
            },
            'hLXma': function _0x55adaf(_0x45a871, _0x161bdf) {
    
                return _0x45a871 + _0x161bdf;
            },
            'JdOlO': function _0x13e00a(_0x5899a9, _0x4bb34d) {
    
                return _0x5899a9 + _0x4bb34d;
            },
            'qrTpg': function _0x1198fb(_0x55b317, _0x22e1db, _0x1b091a) {
    
                return _0x55b317(_0x22e1db, _0x1b091a);
            },
            'pdmMk': function _0xe2b022(_0x4af286, _0x4c2fd4) {
    
                return _0x4af286 - _0x4c2fd4;
            },
            'xVKWW': function _0x1094a3(_0x5f3627, _0x2a0ac5, _0x3ad2e5) {
    
                return _0x5f3627(_0x2a0ac5, _0x3ad2e5);
            }
        };
        if (_0x51eedc[_0x2246('0x258', '@1Ws')](_0x2246('0x259', 'E&PI'), _0x51eedc['wnfPa'])) {
    
            this['_append'](a);
            return this[_0x2246('0x25a', 'GL3Q')]();
        } else {
    
            var _0x492a62 = _0x51eedc[_0x2246('0x25b', '&59Q')][_0x2246('0x25c', ')q#9')]('|')
              , _0x356b01 = 0x0;
            while (!![]) {
    
                switch (_0x492a62[_0x356b01++]) {
    
                case '0':
                    _0x554c90 = _grsa_JS[_0x2246('0x25d', 'E&PI')]['decrypt']({
    
                        'ciphertext': _grsa_JS['enc'][_0x2246('0x25e', 'sy^o')]['parse'](_0xa0c834)
                    }, _0x2cf8ae, {
    
                        'iv': _0x554c90,
                        'mode': _grsa_JS[_0x2246('0x16c', 'O^50')][_0x2246('0x25f', 'Who^')],
                        'padding': _grsa_JS[_0x2246('0x260', '7IfV')][_0x2246('0x261', 'E&PI')]
                    })[_0x2246('0x1c', 'yY#5')](_grsa_JS['enc'][_0x2246('0x262', ']2BX')]);
                    continue;
                case '1':
                    if (_0x51eedc[_0x2246('0x263', 'Jsmq')](null, _0xa0c834) || _0x51eedc[_0x2246('0x264', '!2eC')](0x10, _0xa0c834['length']))
                        return _0xa0c834;
                    continue;
                case '2':
                    _0xa0c834 = _0x9843d3(_0xa0c834, _0x2cf8ae, 0x8);
                    continue;
                case '3':
                    _0x2cf8ae = _grsa_JS[_0x2246('0x265', 'RQ2o')][_0x2246('0x266', '3j7z')][_0x2246('0x267', 'RQ2o')](_0x554c90);
                    continue;
                case '4':
                    return _0x554c90[_0x2246('0x268', 'cs*4')](0x0, _0x51eedc[_0x2246('0x269', 'MVsm')](_0x554c90[_0x2246('0x26a', '0J6f')]('}'), 0x1));
                case '5':
                    _0x554c90 = _0xa0c834[_0x2246('0x26b', 'UwHa')](_0x2cf8ae, 0x8);
                    continue;
                case '6':
                    _0x554c90 = _grsa_JS[_0x2246('0x26c', '4VZ$')]['Utf8']['parse'](_0x554c90);
                    continue;
                case '7':
                    if (!navigator || !navigator[_0x2246('0x26d', '0I#o')])
                        return '';
                    continue;
                case '8':
                    var _0x554c90 = _0x51eedc[_0x2246('0x26e', 'Yb4P')](_0x51eedc[_0x2246('0x26f', 'BQ5p')](parseInt, _0xa0c834[_0x51eedc[_0x2246('0x270', 'Z2VK')](_0xa0c834['length'], 0x1)], 0x10), 0x9)
                      , _0x2cf8ae = _0x51eedc[_0x2246('0x271', 'yY#5')](parseInt, _0xa0c834[_0x554c90], 0x10);
                    continue;
                case '9':
                    _0xa0c834 = _0x9843d3(_0xa0c834, _0x554c90, 0x1);
                    continue;
                }
                break;
            }
        }
    }
    ;
}

可以把第一行和最后两行干掉,我们主要分析那个为this.shell即这个js里的this[_0x2246(‘0x257’, ‘nArV’)]

this.shell = function(_0xa0c834) {
    
        var _0x51eedc = {
    
            'pKENi': function _0x2f627(_0x5b6f5a, _0x440924) {
    
                return _0x5b6f5a === _0x440924;
            },
            'wnfPa': 'ZGz',
            'VMmle': '7|1|8|9|5|2|3|6|0|4',
            'GKWFf': function _0x1a4e13(_0x40cfde, _0x16f3c2) {
    
                return _0x40cfde == _0x16f3c2;
            },
            'MUPgQ': function _0x342f0d(_0x19038b, _0x4004d6) {
    
                return _0x19038b >= _0x4004d6;
            },
            'hLXma': function _0x55adaf(_0x45a871, _0x161bdf) {
    
                return _0x45a871 + _0x161bdf;
            },
            'JdOlO': function _0x13e00a(_0x5899a9, _0x4bb34d) {
    
                return _0x5899a9 + _0x4bb34d;
            },
            'qrTpg': function _0x1198fb(_0x55b317, _0x22e1db, _0x1b091a) {
    
                return _0x55b317(_0x22e1db, _0x1b091a);
            },
            'pdmMk': function _0xe2b022(_0x4af286, _0x4c2fd4) {
    
                return _0x4af286 - _0x4c2fd4;
            },
            'xVKWW': function _0x1094a3(_0x5f3627, _0x2a0ac5, _0x3ad2e5) {
    
                return _0x5f3627(_0x2a0ac5, _0x3ad2e5);
            }
        };
        if (_0x51eedc[_0x2246('0x258', '@1Ws')](_0x2246('0x259', 'E&PI'), _0x51eedc['wnfPa'])) {
    
            this['_append'](a);
            return this[_0x2246('0x25a', 'GL3Q')]();
        } else {
    
            var _0x492a62 = _0x51eedc[_0x2246('0x25b', '&59Q')][_0x2246('0x25c', ')q#9')]('|')
              , _0x356b01 = 0x0;
            while (!![]) {
    
                switch (_0x492a62[_0x356b01++]) {
    
                case '0':
                    _0x554c90 = _grsa_JS[_0x2246('0x25d', 'E&PI')]['decrypt']({
    
                        'ciphertext': _grsa_JS['enc'][_0x2246('0x25e', 'sy^o')]['parse'](_0xa0c834)
                    }, _0x2cf8ae, {
    
                        'iv': _0x554c90,
                        'mode': _grsa_JS[_0x2246('0x16c', 'O^50')][_0x2246('0x25f', 'Who^')],
                        'padding': _grsa_JS[_0x2246('0x260', '7IfV')][_0x2246('0x261', 'E&PI')]
                    })[_0x2246('0x1c', 'yY#5')](_grsa_JS['enc'][_0x2246('0x262', ']2BX')]);
                    continue;
                case '1':
                    if (_0x51eedc[_0x2246('0x263', 'Jsmq')](null, _0xa0c834) || _0x51eedc[_0x2246('0x264', '!2eC')](0x10, _0xa0c834['length']))
                        return _0xa0c834;
                    continue;
                case '2':
                    _0xa0c834 = _0x9843d3(_0xa0c834, _0x2cf8ae, 0x8);
                    continue;
                case '3':
                    _0x2cf8ae = _grsa_JS[_0x2246('0x265', 'RQ2o')][_0x2246('0x266', '3j7z')][_0x2246('0x267', 'RQ2o')](_0x554c90);
                    continue;
                case '4':
                    return _0x554c90[_0x2246('0x268', 'cs*4')](0x0, _0x51eedc[_0x2246('0x269', 'MVsm')](_0x554c90[_0x2246('0x26a', '0J6f')]('}'), 0x1));
                case '5':
                    _0x554c90 = _0xa0c834[_0x2246('0x26b', 'UwHa')](_0x2cf8ae, 0x8);
                    continue;
                case '6':
                    _0x554c90 = _grsa_JS[_0x2246('0x26c', '4VZ$')]['Utf8']['parse'](_0x554c90);
                    continue;
                case '7':
                    if (!navigator || !navigator[_0x2246('0x26d', '0I#o')])
                        return '';
                    continue;
                case '8':
                    var _0x554c90 = _0x51eedc[_0x2246('0x26e', 'Yb4P')](_0x51eedc[_0x2246('0x26f', 'BQ5p')](parseInt, _0xa0c834[_0x51eedc[_0x2246('0x270', 'Z2VK')](_0xa0c834['length'], 0x1)], 0x10), 0x9)
                      , _0x2cf8ae = _0x51eedc[_0x2246('0x271', 'yY#5')](parseInt, _0xa0c834[_0x554c90], 0x10);
                    continue;
                case '9':
                    _0xa0c834 = _0x9843d3(_0xa0c834, _0x554c90, 0x1);
                    continue;
                }
                break;
            }
        }
    }

_0x51eedc这个先不看,就正常声明一个对象。

接下来我们的工作就是重复性的还原变量了,比如在下面if里面有_0x2246(‘0x258’, ‘@1Ws’)这种,先在浏览器控制台输出看一下

在这里插入图片描述
就这样在js里替换下来,所以第一个if还原:
在这里插入图片描述
我们看一下_0x51eedc[‘pKENi’]是干嘛的,在上面在这里插入图片描述
就是传入两个参数判断是否相等。

我们就需要比较一下字符串’tgg ‘和 _0x51eedc[‘wnfPa’]是否相等就行了。而_0x51eedc[‘wnfPa’]还在上面,就是’ZGz’,明显不相等,返回false。既然这个if 条件恒为false,那我们也不用看里面的逻辑了,直接看else里的,把if条件和else花括号都可以干掉了,接着往下走,接着还原;
在这里插入图片描述

'VMmle’就是 ‘7|1|8|9|5|2|3|6|0|4’,那这句就可以替换为:

var _0x492a62 = '7|1|8|9|5|2|3|6|0|4'.split('|')

就是以|分割开成一个数组
在这里插入图片描述

var _0x492a62 = ['7', '1', '8', '9', '5', '2', '3', '6', '0', '4']

在这里插入图片描述
_0x356b01 = 0x0就是_0x356b01 = 0,那个switch就是从数组7(case7)到最后的4顺序执行。
并且可以看到程序执行到最后的4的时候直接return,程序终止,所有各个case只执行了一遍,我们先看7,在这里插入图片描述

它就判断一下有没有userAgent,其实想想程序不可能第一步到这就直接return终止,不然不是白费劲了吗?所以7啥也没干,对我们的数据没有任何影响,可以干掉了,接下来我们直接按顺序把各个case里的代码提出来就可以干掉while了。

 if (_0x51eedc[_0x2246('0x263', 'Jsmq')](null, _0xa0c834) || _0x51eedc[_0x2246('0x264', '!2eC')](0x10, _0xa0c834['length']))
                        return _0xa0c834;
    
    var _0x554c90 = _0x51eedc[_0x2246('0x26e', 'Yb4P')](_0x51eedc[_0x2246('0x26f', 'BQ5p')](parseInt, _0xa0c834[_0x51eedc[_0x2246('0x270', 'Z2VK')](_0xa0c834['length'], 0x1)], 0x10), 0x9)
                      , _0x2cf8ae = _0x51eedc[_0x2246('0x271', 'yY#5')](parseInt, _0xa0c834[_0x554c90], 0x10);
    
    

     _0xa0c834 = _0x9843d3(_0xa0c834, _0x554c90, 0x1);
     
     _0x554c90 = _0xa0c834[_0x2246('0x26b', 'UwHa')](_0x2cf8ae, 0x8);
     
      _0xa0c834 = _0x9843d3(_0xa0c834, _0x2cf8ae, 0x8);
      
      _0x2cf8ae = _grsa_JS[_0x2246('0x265', 'RQ2o')][_0x2246('0x266', '3j7z')][_0x2246('0x267', 'RQ2o')](_0x554c90);
      
      _0x554c90 = _grsa_JS[_0x2246('0x26c', '4VZ$')]['Utf8']['parse'](_0x554c90);
      
      _0x554c90 = _grsa_JS[_0x2246('0x25d', 'E&PI')]['decrypt']({
    
                        'ciphertext': _grsa_JS['enc'][_0x2246('0x25e', 'sy^o')]['parse'](_0xa0c834)
                    }, _0x2cf8ae, {
    
                        'iv': _0x554c90,
                        'mode': _grsa_JS[_0x2246('0x16c', 'O^50')][_0x2246('0x25f', 'Who^')],
                        'padding': _grsa_JS[_0x2246('0x260', '7IfV')][_0x2246('0x261', 'E&PI')]
                    })[_0x2246('0x1c', 'yY#5')](_grsa_JS['enc'][_0x2246('0x262', ']2BX')]);
      
      return _0x554c90[_0x2246('0x268', 'cs*4')](0x0, _0x51eedc[_0x2246('0x269', 'MVsm')](_0x554c90[_0x2246('0x26a', '0J6f')]('}'), 0x1));

接着还原,先看第一个
在这里插入图片描述

看一下_0x51eedc[‘GKWFf’]是个啥,

在这里插入图片描述

就判断是否相等。_0xa0c834明显就是我们传过来的data加密数据呀,怎么可能等于null,所以不成立,再看后面的_0x51eedc[‘MUPgQ’]是个啥:
在这里插入图片描述

就判断第一个参数数是否大于等于第二个参数,这里是判断10受否大于等于我们加密数据的长度,从前面我们知道我们的加密data远大于10,所以很明显也不成立。所以这个if可以直接干掉了。

接着还原往下看:

在这里插入图片描述

那个加密的数据,_0xa0c834看着太难受了,我们直接全局给他替换为data,
在这里插入图片描述

这样看着就好受多了,接着看
在这里插入图片描述

替换为
在这里插入图片描述

在这里插入图片描述
替换为

在这里插入图片描述
这一行的意思就是data的最后一位数据由16进制转化成十进制再加9就完事了。

第二行也是这样的逻辑还原
在这里插入图片描述
继续往下还原,data = 那一行先不管,继续往下把所有的能还原的还原出来

在这里插入图片描述

到这里就可以看出是要用des解密了。最后return一行就是去掉}以外的内容保留json数据。

现在可以把和data = 相关的_0x9843d3 还原一下
在这里插入图片描述
在这里插入图片描述

至此所有的逆向工作已经基本完成了。

最后一步,python还原js算法

接下来我们就用python直接还原,

代码示例:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : 冰履踏青云
# @File    : yien.py

import requests
import binascii
from Crypto.Cipher import DES
headers = {
    
    'Connection': 'keep-alive',
    'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"',
    'Accept': 'text/plain, */*; q=0.01',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'X-Requested-With': 'XMLHttpRequest',
    'sec-ch-ua-mobile': '?0',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36',
    'sec-ch-ua-platform': '"Windows"',
    'Origin': 'https://www.endata.com.cn',
    'Sec-Fetch-Site': 'same-origin',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Dest': 'empty',
    'Accept-Language': 'zh-CN,zh;q=0.9',
}

data = {
    
    'year': '2022',
    'MethodName': 'BoxOffice_GetYearInfoData',
}

response = requests.post('https://www.endata.com.cn/API/GetData.ashx', headers=headers, data=data)
data = response.text
# print(data)

def _0x9843d3(aa,bb,cc):
    if 0 == bb:
        return aa[cc:]
    _0x48914b = '' + aa[:bb]

    _0x48914b += aa[(bb+cc):]
    return _0x48914b

a = int(data[-1],16) +9
b = int(data[a],16)
data = _0x9843d3(data, a, 1)
a = data[b:b+8]
data = _0x9843d3(data, b, 8)
b = a.encode('utf-8')
a = a.encode('utf-8')
# 16 转二进制
dt = binascii.a2b_hex(data)
des = DES.new(b,mode=DES.MODE_ECB)
res = des.decrypt(dt).decode('utf-8')
print(res)



结果:
在这里插入图片描述

可以看到看着很复杂的js代码,一旦捋清逻辑就变得很简单。

这个案例难度倒是不大,就是有点绕,需要我们耐心找寻规律,做逆向切忌心浮气躁,一步一个脚印,终会柳暗花明。

往期逆向文章推荐:

JS逆向之百度翻译

JS逆向解析之有道翻译

JS逆向之企名科技

JS逆向之人口流动态势

js逆向系列之猿人学爬虫第12题

js逆向系列之猿人学爬虫第13题

js逆向系列之猿人学爬虫第17题

很早以前就打算开个逆向百例专栏,后面一直没有时间写,很多已经做好的项目没有保留逆向过程,直接上代码就有点尴尬,后面慢慢看吧,有时间就补补贴出来。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44327634/article/details/125116971

智能推荐

ubuntu桌面版打开终端Terminal的几种方法_mate 桌面查看当前桌面所有终端-程序员宅基地

文章浏览阅读3w次,点赞7次,收藏8次。1. Ctrl + Alt + T 快捷键直接打开2. 在Ubuntu左上角选择File/Open in Terminal3. 快捷键alt+F2调出Run a Command,输入gnome-terminal4. 通过dash home这个按钮,输入te,就可以看到Terminal终端的选项了,如下图:_mate 桌面查看当前桌面所有终端

(JavaScript学习记录):BOM 浏览器对象模型-程序员宅基地

文章浏览阅读360次。写在前面:参考哔哩哔哩黑马程序员pink老师教程 地址:https://www.bilibili.com/video/BV1Sy4y1C7ha?t=41&p=4目录BOM 浏览器对象模型BOM 概述什么是 BOMBOM 的构成window 对象的常见事件窗口加载事件调整窗口大小事件定时器setTimeout() 定时器案例: 5秒后自动关闭的广告停止 setTimeout() 定时器setInterval() 定时器案例: 倒计时停止 .

echarts的y轴自适应,不从0开始_echarts y轴自适应-程序员宅基地

文章浏览阅读2.6w次,点赞14次,收藏26次。echarts的y轴自适应,不从0开始最近写项目的时候画图工具用的esharts,还是比较不错,但是做一个折线图的时候遇到个问题。可以看到如果数值接近,那么曲线就不会很明显,最后找到个属性。scale:true加上之后就可以自由伸展了。option = { xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], }, yAxis_echarts y轴自适应

Linux core文件的生成、大小、路径查看和设置_linux查看core文件路径-程序员宅基地

文章浏览阅读5.8k次。1.设置core文件大小1)使用ulimit -c命令可查看core文件的生成开关。若结果为0,则表示关闭了此功能,不会生成core文件。2)使用ulimit -c filesize命令,可以限制core文件的大小(filesize的单位为kbyte)。若ulimit -c unlimited,则表示core文件的大小不受限制。如果生成的信息超过此大小,将会被裁剪,最终生成一个不完整的core文件。在调试此core文 件的时候,gdb会提示错误。可以将ulimit -c unlimited写入到.ba_linux查看core文件路径

等价类结和判定表的软件测试方法应用-程序员宅基地

文章浏览阅读626次。摘要:软件测试的类型通常分为白盒测试和黑盒测试,其中基于等价类的划分法与基于判定表的测试法都是较为典型和实用的黑盒测试技术方法。在实际工作中,为了使测试用例的覆盖更加全面,测试目的更加明确,通常不仅仅局限于某一种测试手段。针对等价类和判定表这两种方法各自的特点,可以将两者有机结合,通过对输入条件进行等价类划分,对输出行为进行判定表列举,用综合的手段进行软..._测试用例等价类和判定表合用

蓝桥杯 BASIC-15 基础练习 字符串对比_字符对比-程序员宅基地

文章浏览阅读79次。问题描述  给定两个仅由大写字母或小写字母组成的字符串(长度介于1到10之间),它们之间的关系是以下4中情况之一:  1:两个字符串长度不等。比如 Beijing 和 Hebei  2:两个字符串不仅长度相等,而且相应位置上的字符完全一致(区分大小写),比如 Beijing 和 Beijing  3:两个字符串长度相等,相应位置上的字符仅在不区分大小写的前提下才能达到完全一致(也就是说,它并不满足情况2)。比如 beijing 和 BEIjing  4:两个字符串长度相等,但是即使是不区分大小写也_字符对比

随便推点

RedisDesktopManager启动后不显示窗口_为什么another redis desktop manager打开后是白屏-程序员宅基地

文章浏览阅读2.4k次,点赞13次,收藏6次。一、问题描述每次打开RDM的时候,只显示了更新提示窗口,而主窗口却并没有显示(双屏都没有显示),通过Alt + Tab检查发现,软件是正常打开的。二、解决办法首先按alt+tab键,确保该窗口处于激活位置(或者任务栏选中这个RDM) 然后再按alt+space键,激活控制菜单(注意快捷键别被占用,如:uTool快键键就是这个) 再按m键(按住不放),上下左右操作,将窗口移到屏幕中间位置即可三、相关图片..._为什么another redis desktop manager打开后是白屏

Echart添加title等样式不显示_为什么 pyecharts的标题不显示-程序员宅基地

文章浏览阅读2.1k次。检查是否报错 ,是否将title等组件引入清除浏览器缓存(踩过的坑)_为什么 pyecharts的标题不显示

python3.7 sqlalchemy模块的安装与使用_安装sqlalchemy-程序员宅基地

文章浏览阅读1.6w次,点赞6次,收藏9次。python3.7 sqlalchemy模块的安装与使用1、sqlalchemy是什么:SQLAlchemy是Python编程语言下的一款开源软件。提供了SQL工具包及对象关系映射(ORM)工具,使用MIT许可证发行。SQLAlchemy“采用简单的Python语言,为高效和高性能的数据库访问设计,实现了完整的企业级持久模型”。SQLAlchemy的理念是,SQL数据库的量级和性能重要于对象..._安装sqlalchemy

gh auth login时引起的could not prompt: Incorrect function.问题-程序员宅基地

文章浏览阅读1k次。错误描述$ gh auth login? What account do you want to log into? [Use arrows to move, type to filter]> GitHub.com GitHub Enterprise Servercould not prompt: Incorrect function.You appear to be running in MinTTY without pseudo terminal support.To learn_gh auth login

2018/09/25Web前端学习第一课_2.维护简单方便、易于升级-程序员宅基地

文章浏览阅读277次。今日作业1.什么是BS架构和CS架构的程序,各有何优缺点;2.浏览器有哪些,什么是标准浏览器;3.将如下的HTML片段代码进行格式化,并将格式化好的代码贴在CSDN中第一题什么是BS架构的程序B/S(Browser/Server)结构即浏览器和服务器结构。它是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构。在这种结构下,用户工作界面是通过WWW浏览器来实现,极少..._2.维护简单方便、易于升级

java实现合并多个线段,计算多个线段的实际覆盖长度_java 多条线段合并为一条线-程序员宅基地

文章浏览阅读1.7k次。算法: 计算多个线段实际覆盖的长度。例如:线段组1:{{1, 2}, {2, 3}, {3, 5}, {4, 10.5}, {11, 13}}的长度为[1,10.5],[11,13]的长度为11.5;线段组2:{{1, 5}, {4, 5}, {0.7, 6}, {0.9, 1.5}}的长度为[0.7,6]的长度为5.3;思路分析:1.由题意知道: 要求实际长度,凡是两个线段有重叠的地..._java 多条线段合并为一条线

推荐文章

热门文章

相关标签